blob: 841f49a3b0f5594ffcdff31f58c45d6f69939bd2 [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 */
Dave Thaler93c01182022-08-06 15:08:35 -0400508#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800509#pragma GCC diagnostic push
510#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400511#endif
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800512 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
Dave Thaler93c01182022-08-06 15:08:35 -0400513#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800514#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400515#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800516}
517
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518// StringAllocator_Reallocate called with pMem NULL is
519// equal to StringAllocator_Allocate()
520static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800521StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800522 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800525 /* See comment in StringAllocator_Free() */
Dave Thaler93c01182022-08-06 15:08:35 -0400526#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800527#pragma GCC diagnostic push
528#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400529#endif
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800530 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
Dave Thaler93c01182022-08-06 15:08:35 -0400531#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800532#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400533#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534}
535
Laurence Lundbladeee851742020-01-08 08:37:05 -0800536static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800537StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800538{
539 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
540}
541
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800543StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800545 /* See comment in StringAllocator_Free() */
Dave Thaler93c01182022-08-06 15:08:35 -0400546#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800547#pragma GCC diagnostic push
548#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400549#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800550 if(pMe->pfAllocator) {
551 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
552 }
Dave Thaler93c01182022-08-06 15:08:35 -0400553#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800554#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400555#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800557#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558
559
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800560
561
Laurence Lundbladeee851742020-01-08 08:37:05 -0800562/*===========================================================================
563 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800565 See qcbor/qcbor_decode.h for definition of the object
566 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800569 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800571void QCBORDecode_Init(QCBORDecodeContext *pMe,
572 UsefulBufC EncodedCBOR,
573 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800575 memset(pMe, 0, sizeof(QCBORDecodeContext));
576 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
577 /* Don't bother with error check on decode mode. If a bad value is
578 * passed it will just act as if the default normal mode of 0 was set.
579 */
580 pMe->uDecodeMode = (uint8_t)nDecodeMode;
581 DecodeNesting_Init(&(pMe->nesting));
582
583 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
584 * GetNext_TaggedItem() and MapTagNumber(). */
585 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586}
587
588
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800589#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
590
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800592 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700593 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
595 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800596 void *pAllocateContext,
597 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800599 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
600 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
601 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700602}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800603#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800606
607
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800608/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800609 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800611void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800612 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700613{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800614 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700615 (void)pMe;
616 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700617}
618
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700619
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800620
621
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800623 * Decoding items is done in six layers, one calling the next one
624 * down. If a layer has no work to do for a particular item, it
625 * returns quickly.
626 *
627 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
628 * data items, turning them into the local C representation. For the
629 * most simple it is just associating a QCBOR_TYPE with the data. For
630 * the complex ones that an aggregate of data items, there is some
631 * further decoding and some limited recursion.
632 *
633 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
634 * ends of maps and arrays. It tracks descending into and ascending
635 * out of maps/arrays. It processes breaks that terminate
636 * indefinite-length maps and arrays.
637 *
638 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
639 * items, the label and the data, that make up a map entry. It only
640 * does work on maps. It combines the label and data items into one
641 * labeled item.
642 *
643 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
644 * numbers. It turns the tag numbers into bit flags associated with
645 * the data item. No actual decoding of the contents of the tag is
646 * performed here.
647 *
648 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
649 * that make up an indefinite-length string into one string item. It
650 * uses the string allocator to create contiguous space for the
651 * item. It processes all breaks that are part of indefinite-length
652 * strings.
653 *
654 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
655 * CBOR. Each atomic data item has a "major type", an integer
656 * "argument" and optionally some content. For text and byte strings,
657 * the content is the bytes that make up the string. These are the
658 * smallest data items that are considered to be well-formed. The
659 * content may also be other data items in the case of aggregate
660 * types. They are not handled in this layer.
661 *
662 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
663 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800665
666
667/*
668 * Note about use of int and unsigned variables.
669 *
670 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
671 * used carefully here, and in particular why it isn't used in the
672 * public interface. Also see
673 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
674 *
675 * Int is used for values that need less than 16-bits and would be
676 * subject to integer promotion and result in complaining from static
677 * analyzers.
678 */
679
680
681/**
682 * @brief Decode the CBOR head, the type and argument.
683 *
684 * @param[in] pUInBuf The input buffer to read from.
685 * @param[out] pnMajorType The decoded major type.
686 * @param[out] puArgument The decoded argument.
687 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
688 *
689 * @retval QCBOR_ERR_UNSUPPORTED
690 * @retval QCBOR_ERR_HIT_END
691 *
692 * This decodes the CBOR "head" that every CBOR data item has. See
693 * longer explaination of the head in documentation for
694 * QCBOREncode_EncodeHead().
695 *
696 * This does the network->host byte order conversion. The conversion
697 * here also results in the conversion for floats in addition to that
698 * for lengths, tags and integer values.
699 *
700 * The int type is preferred to uint8_t for some variables as this
701 * avoids integer promotions, can reduce code size and makes static
702 * analyzers happier.
703 */
704static inline QCBORError
705DecodeHead(UsefulInputBuf *pUInBuf,
706 int *pnMajorType,
707 uint64_t *puArgument,
708 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800710 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800711
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800712 /* Get the initial byte that every CBOR data item has and break it
713 * down. */
714 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800715 const int nTmpMajorType = nInitialByte >> 5;
716 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800717
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800718 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800719 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 /* Need to get 1,2,4 or 8 additional argument bytes. Map
723 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
724 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800725 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800728 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800730 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800731 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
732 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800734 /* The reserved and thus-far unused additional info values */
735 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800736 goto Done;
737 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800738 /* Less than 24, additional info is argument or 31, an
739 * indefinite-length. No more bytes to get.
740 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 goto Done;
747 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800748
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800749 /* All successful if arrived here. */
750 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800751 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800752 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800756 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757}
758
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800760/**
761 * @brief Decode integer types, major types 0 and 1.
762 *
763 * @param[in] nMajorType The CBOR major type (0 or 1).
764 * @param[in] uArgument The argument from the head.
765 * @param[out] pDecodedItem The filled in decoded item.
766 *
767 * @retval QCBOR_ERR_INT_OVERFLOW
768 *
769 * Must only be called when major type is 0 or 1.
770 *
771 * CBOR doesn't explicitly specify two's compliment for integers but
772 * all CPUs use it these days and the test vectors in the RFC are
773 * so. All integers in the CBOR structure are positive and the major
774 * type indicates positive or negative. CBOR can express positive
775 * integers up to 2^x - 1 where x is the number of bits and negative
776 * integers down to 2^x. Note that negative numbers can be one more
777 * away from zero than positive. Stdint, as far as I can tell, uses
778 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700779 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700780static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800781DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800783 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800784
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800786 if (uArgument <= INT64_MAX) {
787 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800796 if(uArgument <= INT64_MAX) {
797 /* CBOR's representation of negative numbers lines up with
798 * the two-compliment representation. A negative integer has
799 * one more in range than a positive integer. INT64_MIN is
800 * equal to (-INT64_MAX) - 1.
801 */
802 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800804
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800806 /* C can't represent a negative integer in this range so it
807 * is an error.
808 */
809 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810 }
811 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700814}
815
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800816
817/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
819#error QCBOR_TYPE_FALSE macro value wrong
820#endif
821
822#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
823#error QCBOR_TYPE_TRUE macro value wrong
824#endif
825
826#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
827#error QCBOR_TYPE_NULL macro value wrong
828#endif
829
830#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
831#error QCBOR_TYPE_UNDEF macro value wrong
832#endif
833
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700834#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
835#error QCBOR_TYPE_BREAK macro value wrong
836#endif
837
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
839#error QCBOR_TYPE_DOUBLE macro value wrong
840#endif
841
842#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
843#error QCBOR_TYPE_FLOAT macro value wrong
844#endif
845
Laurence Lundblade9b334962020-08-27 10:55:53 -0700846
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847/**
848 * @brief Decode major type 7 -- true, false, floating-point, break...
849 *
850 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
851 * @param[in] uArgument The argument from the head.
852 * @param[out] pDecodedItem The filled in decoded item.
853 *
854 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200855 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800856 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800859static inline QCBORError
860DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
861{
862 QCBORError uReturn = QCBOR_SUCCESS;
863
864 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
865 * checks above make sure uAdditionalInfo values line up with
866 * uDataType values. DecodeHead() never returns an AdditionalInfo
867 * > 0x1f so cast is safe.
868 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800869 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800871 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
873 * are caught before this is called.
874 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800876 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700877#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800878 /* Half-precision is returned as a double. The cast to
879 * uint16_t is safe because the encoded value was 16 bits. It
880 * was widened to 64 bits to be passed in here.
881 */
882 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700883 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800884#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200885 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700886 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200888#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800889 /* Single precision is normally returned as a double since
890 * double is widely supported, there is no loss of precision,
891 * it makes it easy for the caller in most cases and it can
892 * be converted back to single with no loss of precision
893 *
894 * The cast to uint32_t is safe because the encoded value was
895 * 32 bits. It was widened to 64 bits to be passed in here.
896 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700897 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800898 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700899#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800900 /* In the normal case, use HW to convert float to
901 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700902 pDecodedItem->val.dfnum = (double)f;
903 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800904#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800905 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700906 pDecodedItem->val.fnum = f;
907 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
908
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800909 /* IEEE754_FloatToDouble() could be used here to return as
910 * a double, but it adds object code and most likely
911 * anyone disabling FLOAT HW use doesn't care about floats
912 * and wants to save object code.
913 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800914#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700915 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200916#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
917 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700918 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700919
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800920 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200921#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800922 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700923 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200924#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
925 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700926 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800928 case CBOR_SIMPLEV_FALSE: /* 20 */
929 case CBOR_SIMPLEV_TRUE: /* 21 */
930 case CBOR_SIMPLEV_NULL: /* 22 */
931 case CBOR_SIMPLEV_UNDEF: /* 23 */
932 case CBOR_SIMPLE_BREAK: /* 31 */
933 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
936 if(uArgument <= CBOR_SIMPLE_BREAK) {
937 /* This takes out f8 00 ... f8 1f which should be encoded
938 * as e0 … f7
939 */
940 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 goto Done;
942 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800943 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800945 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800947 /* DecodeHead() will make uArgument equal to
948 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
949 * safe because the 2, 4 and 8 byte lengths of uNumber are in
950 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800952 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953 break;
954 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700956Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800957 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958}
959
960
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800961/**
962 * @brief Decode text and byte strings
963 *
964 * @param[in] pAllocator The string allocator or NULL.
965 * @param[in] uStrLen The length of the string.
966 * @param[in] pUInBuf The surce from which to read the string's bytes.
967 * @param[out] pDecodedItem The filled in decoded item.
968 *
969 * @retval QCBOR_ERR_HIT_END
970 * @retval QCBOR_ERR_STRING_ALLOCATE
971 * @retval QCBOR_ERR_STRING_TOO_LONG
972 *
973 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
974 * pDecodedItem. If @c pAllocator is not NULL then memory for the
975 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800977static inline QCBORError
978DecodeBytes(const QCBORInternalAllocator *pAllocator,
979 uint64_t uStrLen,
980 UsefulInputBuf *pUInBuf,
981 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800985 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
986 * CPUs. This check makes the casts to size_t below safe.
987 *
988 * The max is 4 bytes less than the largest sizeof() so this can be
989 * tested by putting a SIZE_MAX length in the CBOR test input (no
990 * one will care the limit on strings is 4 bytes shorter).
991 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800992 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800994 goto Done;
995 }
996
997 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530998 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800999 /* Failed to get the bytes for this string item */
1000 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301001 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301003
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001004#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005 /* Note that this is not where allocation to coalesce
1006 * indefinite-length strings is done. This is for when the caller
1007 * has requested all strings be allocated. Disabling indefinite
1008 * length strings also disables this allocate-all option.
1009 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001010 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001011 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301013 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001014 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301015 goto Done;
1016 }
1017 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001018 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001019 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301020 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1022 (void)pAllocator;
1023#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1024
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001025 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001026 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301028Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001029 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030}
1031
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001032
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001033/**
1034 * @brief Map the CBOR major types for strings to the QCBOR types.
1035 *
1036 * @param[in] nCBORMajorType The CBOR major type to convert.
1037 * @retturns QCBOR type number.
1038 *
1039 * This only works for the two string types.
1040 */
1041static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001042{
1043 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1044 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1045 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001046
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001047 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1048 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1049 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051 return (uint8_t)(nCBORMajorType + 4);
1052}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053
1054
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001055/**
1056 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1057 *
1058 * @param[in] nCBORMajorType The CBOR major type to convert.
1059 * @retturns QCBOR type number.
1060 *
1061 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001062 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001063static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001065 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1066 #error QCBOR_TYPE_ARRAY value not lined up with major type
1067 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001069 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1070 #error QCBOR_TYPE_MAP value not lined up with major type
1071 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001073 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074}
1075
1076
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001077/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001078 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080 * @param[in] pUInBuf Input buffer to read data item from.
1081 * @param[out] pDecodedItem The filled-in decoded item.
1082 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001083 *
1084 * @retval QCBOR_ERR_UNSUPPORTED
1085 * @retval QCBOR_ERR_HIT_END
1086 * @retval QCBOR_ERR_INT_OVERFLOW
1087 * @retval QCBOR_ERR_STRING_ALLOCATE
1088 * @retval QCBOR_ERR_STRING_TOO_LONG
1089 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001090 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001091 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001092 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1093 *
1094 * This decodes the most primitive / atomic data item. It does
1095 * no combing of data items.
1096 */
1097static QCBORError
1098DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1099 QCBORItem *pDecodedItem,
1100 const QCBORInternalAllocator *pAllocator)
1101{
1102 QCBORError uReturn;
1103
1104 /* Get the major type and the argument. The argument could be
1105 * length of more bytes or the value depending on the major
1106 * type. nAdditionalInfo is an encoding of the length of the
1107 * uNumber and is needed to decode floats and doubles.
1108 */
1109 int nMajorType = 0;
1110 uint64_t uArgument = 0;
1111 int nAdditionalInfo = 0;
1112
1113 memset(pDecodedItem, 0, sizeof(QCBORItem));
1114
1115 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1116 if(uReturn) {
1117 goto Done;
1118 }
1119
1120 /* At this point the major type and the argument are valid. We've
1121 * got the type and the argument that starts every CBOR data item.
1122 */
1123 switch (nMajorType) {
1124 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1125 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1126 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1127 uReturn = QCBOR_ERR_BAD_INT;
1128 } else {
1129 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1130 }
1131 break;
1132
1133 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1134 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1135 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1136 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1137 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1138 } else {
1139 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1140 }
1141 break;
1142
1143 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1144 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1145 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1146 /* Indefinite-length string. */
1147#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1148 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1149#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1150 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1151 break;
1152#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1153 } else {
1154 /* Definite-length string. */
1155 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1156 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1157 goto Done;
1158 }
1159 /* cast OK because of check above */
1160 pDecodedItem->val.uCount = (uint16_t)uArgument;
1161 }
1162 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1163 break;
1164
1165 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001166#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001167 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1168 uReturn = QCBOR_ERR_BAD_INT;
1169 } else {
1170 pDecodedItem->val.uTagV = uArgument;
1171 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1172 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001173#else /* QCBOR_DISABLE_TAGS */
1174 uReturn = QCBOR_ERR_TAGS_DISABLED;
1175#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001176 break;
1177
1178 case CBOR_MAJOR_TYPE_SIMPLE:
1179 /* Major type 7: float, double, true, false, null... */
1180 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1181 break;
1182
1183 default:
1184 /* Never happens because DecodeHead() should never return > 7 */
1185 uReturn = QCBOR_ERR_UNSUPPORTED;
1186 break;
1187 }
1188
1189Done:
1190 return uReturn;
1191}
1192
1193
1194/**
1195 * @brief Process indefinite-length strings (decode layer 5).
1196 *
1197 * @param[in] pMe Decoder context
1198 * @param[out] pDecodedItem The decoded item that work is done on.
1199 *
1200 * @retval QCBOR_ERR_UNSUPPORTED
1201 * @retval QCBOR_ERR_HIT_END
1202 * @retval QCBOR_ERR_INT_OVERFLOW
1203 * @retval QCBOR_ERR_STRING_ALLOCATE
1204 * @retval QCBOR_ERR_STRING_TOO_LONG
1205 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001206 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207 * @retval QCBOR_ERR_BAD_TYPE_7
1208 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001209 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1210 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001211 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001212 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001213 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001214 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001215 * If it is, this loops getting the subsequent chunk data items that
1216 * make up the string. The string allocator is used to make a
1217 * contiguous buffer for the chunks. When this completes @c
1218 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001219 *
1220 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001221 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001222static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001223QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001224{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001225 /* Aproximate stack usage
1226 * 64-bit 32-bit
1227 * local vars 32 16
1228 * 2 UsefulBufs 32 16
1229 * QCBORItem 56 52
1230 * TOTAL 120 74
1231 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001232
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001233 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001234 * coalescing the chunks of an indefinite-length string, 2)
1235 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001237 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001238 * strings cannot be processed at all without a string allocator.
1239 *
1240 * The second used is in DecodeBytes() which is called by
1241 * GetNext_Item() below. This second use unneccessary for most use
1242 * and only happens when requested in the call to
1243 * QCBORDecode_SetMemPool(). If the second use not requested then
1244 * NULL is passed for the string allocator to GetNext_Item().
1245 *
1246 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1247 * allocator altogether and thus both of these uses. It reduced the
1248 * decoder object code by about 400 bytes.
1249 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001250 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001252#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001253 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001254
1255 if(pMe->StringAllocator.pfAllocator) {
1256 pAllocator = &(pMe->StringAllocator);
1257 if(pMe->bStringAllocateAll) {
1258 pAllocatorForGetNext = pAllocator;
1259 }
1260 }
1261#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1262
1263 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001264 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001265 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001266 goto Done;
1267 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001268
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001269 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001270 const uint8_t uStringType = pDecodedItem->uDataType;
1271 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001272 goto Done;
1273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001274
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001275 /* Is this a string with an indefinite length? */
1276 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1277 goto Done;
1278 }
1279
1280#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001281 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001282 if(pAllocator == NULL) {
1283 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1284 goto Done;
1285 }
1286
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001287 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001288 UsefulBufC FullString = NULLUsefulBufC;
1289
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001290 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001291 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001292 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001293 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001294 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 * be allocated. They are always copied in the the contiguous
1296 * buffer allocated here.
1297 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 if(uReturn) {
1300 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001302
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001303 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001304 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001305 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001306 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301307 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001308 break;
1309 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001310
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001311 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001312 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001313 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001314 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001315 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001316 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001317 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1318 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001319 break;
1320 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001321
David Navarro9123e5b2022-03-28 16:04:03 +02001322 if (StringChunkItem.val.string.len > 0) {
1323 /* The first time throurgh FullString.ptr is NULL and this is
1324 * equivalent to StringAllocator_Allocate(). Subsequently it is
1325 * not NULL and a reallocation happens.
1326 */
1327 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1328 FullString.ptr,
1329 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001330
David Navarro9123e5b2022-03-28 16:04:03 +02001331 if(UsefulBuf_IsNULL(NewMem)) {
1332 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1333 break;
1334 }
1335
1336 /* Copy new string chunk to the end of accumulated string */
1337 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001338 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001339 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001340
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001341 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1342 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001343 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001344 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001345#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1346 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1347#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001348
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001349Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001350 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001351}
1352
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001353
Laurence Lundblade37286c02022-09-03 10:05:02 -07001354#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001355/**
1356 * @brief This converts a tag number to a shorter mapped value for storage.
1357 *
1358 * @param[in] pMe The decode context.
1359 * @param[in] uUnMappedTag The tag number to map
1360 * @param[out] puMappedTagNumer The stored tag number.
1361 *
1362 * @return error code.
1363 *
1364 * The main point of mapping tag numbers is make QCBORItem
1365 * smaller. With this mapping storage of 4 tags takes up 8
1366 * bytes. Without, it would take up 32 bytes.
1367 *
1368 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1369 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1370 *
1371 * See also UnMapTagNumber() and @ref QCBORItem.
1372 */
1373static inline QCBORError
1374MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1375{
1376 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1377 unsigned uTagMapIndex;
1378 /* Is there room in the tag map, or is it in it already? */
1379 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1380 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1381 break;
1382 }
1383 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1384 break;
1385 }
1386 }
1387 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1388 return QCBOR_ERR_TOO_MANY_TAGS;
1389 }
1390
1391 /* Covers the cases where tag is new and were it is already in the map */
1392 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1393 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1394
1395 } else {
1396 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1397 }
1398
1399 return QCBOR_SUCCESS;
1400}
1401
1402
1403/**
1404 * @brief This converts a mapped tag number to the actual tag number.
1405 *
1406 * @param[in] pMe The decode context.
1407 * @param[in] uMappedTagNumber The stored tag number.
1408 *
1409 * @return The actual tag number is returned or
1410 * @ref CBOR_TAG_INVALID64 on error.
1411 *
1412 * This is the reverse of MapTagNumber()
1413 */
1414static uint64_t
1415UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1416{
1417 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1418 return uMappedTagNumber;
1419 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001420 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001421 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001422 /* This won't be negative because of code below in
1423 * MapTagNumber()
1424 */
1425 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1426 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001427 }
1428}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001429#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001430
Laurence Lundblade9b334962020-08-27 10:55:53 -07001431
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001432/**
1433 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1434 *
1435 * @param[in] pMe Decoder context
1436 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001437
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001438 * @retval QCBOR_ERR_UNSUPPORTED
1439 * @retval QCBOR_ERR_HIT_END
1440 * @retval QCBOR_ERR_INT_OVERFLOW
1441 * @retval QCBOR_ERR_STRING_ALLOCATE
1442 * @retval QCBOR_ERR_STRING_TOO_LONG
1443 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001444 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001445 * @retval QCBOR_ERR_BAD_TYPE_7
1446 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1447 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1448 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1449 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1450 * @retval QCBOR_ERR_TOO_MANY_TAGS
1451 *
1452 * This loops getting atomic data items until one is not a tag
1453 * number. Usually this is largely pass-through because most
1454 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001455 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001456static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001457QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001458{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001459#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001460 /* Accummulate the tags from multiple items here and then copy them
1461 * into the last item, the non-tag item.
1462 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001463 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1464
1465 /* Initialize to CBOR_TAG_INVALID16 */
1466 #if CBOR_TAG_INVALID16 != 0xffff
1467 /* Be sure the memset does the right thing. */
1468 #err CBOR_TAG_INVALID16 tag not defined as expected
1469 #endif
1470 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001471
Laurence Lundblade9b334962020-08-27 10:55:53 -07001472 QCBORError uReturn = QCBOR_SUCCESS;
1473
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001474 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001475 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001476 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001477 if(uErr != QCBOR_SUCCESS) {
1478 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001479 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001480 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001481
Laurence Lundblade9b334962020-08-27 10:55:53 -07001482 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001483 /* Successful exit from loop; maybe got some tags, maybe not */
1484 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001485 break;
1486 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001487
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001488 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1489 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001490 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001491 /* Continue on to get all tags wrapping this item even though
1492 * it is erroring out in the end. This allows decoding to
1493 * continue. This is a resource limit error, not a problem
1494 * with being well-formed CBOR.
1495 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001496 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001497 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001498 /* Slide tags over one in the array to make room at index 0.
1499 * Must use memmove because the move source and destination
1500 * overlap.
1501 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001502 memmove(&auItemsTags[1],
1503 auItemsTags,
1504 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001505
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001506 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001507 uint16_t uMappedTagNumber = 0;
1508 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001509 /* Continue even on error so as to consume all tags wrapping
1510 * this data item so decoding can go on. If MapTagNumber()
1511 * errors once it will continue to error.
1512 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001513 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001514 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001515
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001516Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001517 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001518
Laurence Lundblade37286c02022-09-03 10:05:02 -07001519#else /* QCBOR_DISABLE_TAGS */
1520
1521 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1522
1523#endif /* QCBOR_DISABLE_TAGS */
1524}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001525
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001526/**
1527 * @brief Combine a map entry label and value into one item (decode layer 3).
1528 *
1529 * @param[in] pMe Decoder context
1530 * @param[out] pDecodedItem The decoded item that work is done on.
1531 *
1532 * @retval QCBOR_ERR_UNSUPPORTED
1533 * @retval QCBOR_ERR_HIT_END
1534 * @retval QCBOR_ERR_INT_OVERFLOW
1535 * @retval QCBOR_ERR_STRING_ALLOCATE
1536 * @retval QCBOR_ERR_STRING_TOO_LONG
1537 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001538 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001539 * @retval QCBOR_ERR_BAD_TYPE_7
1540 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1541 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1542 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1543 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1544 * @retval QCBOR_ERR_TOO_MANY_TAGS
1545 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1546 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1547 *
1548 * If a the current nesting level is a map, then this
1549 * combines pairs of items into one data item with a label
1550 * and value.
1551 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001552 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001553 * not a map.
1554 *
1555 * This also implements maps-as-array mode where a map
1556 * is treated like an array to allow caller to do their
1557 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001558 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001559static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001560QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001561{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001562 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1563 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001564 goto Done;
1565 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001566
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001567 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1568 /* Break can't be a map entry */
1569 goto Done;
1570 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001571
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001572 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1573 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001574
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001575 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1576 /* Save label in pDecodedItem and get the next which will
1577 * be the real data item.
1578 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001579 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001580 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1581 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001582 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001583 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001584
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301585 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001586
1587 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001588 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001589 pDecodedItem->label.string = LabelItem.val.string;
1590 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001591 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1592 /* It's not a string and we only want strings */
1593 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001594 goto Done;
1595 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1596 pDecodedItem->label.int64 = LabelItem.val.int64;
1597 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1598 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1599 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1600 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1601 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1602 pDecodedItem->label.string = LabelItem.val.string;
1603 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1604 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1605 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001606 /* label is not an int or a string. It is an arrray
1607 * or a float or such and this implementation doesn't handle that.
1608 * Also, tags on labels are ignored.
1609 */
1610 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001611 goto Done;
1612 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001613 }
1614 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001615 /* Decoding of maps as arrays to let the caller decide what to do
1616 * about labels, particularly lables that are not integers or
1617 * strings.
1618 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001619 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001620 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001621 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001622 goto Done;
1623 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001624 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001625 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1626 * Cast is needed because of integer promotion.
1627 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001628 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001629 }
1630 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001631
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001632Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001633 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001634}
1635
1636
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001637#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001638/**
1639 * @brief Peek and see if next data item is a break;
1640 *
1641 * @param[in] pUIB UsefulInputBuf to read from.
1642 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1643 *
1644 * @return Any decoding error.
1645 *
1646 * See if next item is a CBOR break. If it is, it is consumed,
1647 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001648*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001650NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1651{
1652 *pbNextIsBreak = false;
1653 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001654 QCBORItem Peek;
1655 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001656 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001657 if(uReturn != QCBOR_SUCCESS) {
1658 return uReturn;
1659 }
1660 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001661 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001662 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001663 } else {
1664 *pbNextIsBreak = true;
1665 }
1666 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001667
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001668 return QCBOR_SUCCESS;
1669}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001670#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001671
1672
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001673/**
1674 * @brief Ascend up nesting levels if all items in them have been consumed.
1675 *
1676 * @param[in] pMe The decode context.
1677 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1678 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679 * An item was just consumed, now figure out if it was the
1680 * end of an array/map map that can be closed out. That
1681 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001682*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001683static QCBORError
1684QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001685{
1686 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001687
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001689 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1690
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001691 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1692 /* Nesting level is bstr-wrapped CBOR */
1693
1694 /* Ascent for bstr-wrapped CBOR is always by explicit call
1695 * so no further ascending can happen.
1696 */
1697 break;
1698
1699 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1700 /* Level is a definite-length array/map */
1701
1702 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001703 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1704 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001705 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706 break;
1707 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001708 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001709 * is time to ascend one level. This happens below.
1710 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001711
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001712#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001713 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001714 /* Level is an indefinite-length array/map. */
1715
1716 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001717 bool bIsBreak = false;
1718 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1719 if(uReturn != QCBOR_SUCCESS) {
1720 goto Done;
1721 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001722
1723 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001724 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001725 break;
1726 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001727
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001728 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001729 * it is time to ascend one level.
1730 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001731
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001732#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001733 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001734
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001735
1736 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001737
Laurence Lundblade93d89472020-10-03 22:30:50 -07001738 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001739 * QCBORDecode_ExitBoundedMode().
1740 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001741 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001742 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001743 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001744 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001745 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001746 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001747
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001748 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001749 break;
1750 }
1751
1752 /* Finally, actually ascend one level. */
1753 DecodeNesting_Ascend(&(pMe->nesting));
1754 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001755
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001756 uReturn = QCBOR_SUCCESS;
1757
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001758#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001759Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001760#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1761
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001762 return uReturn;
1763}
1764
1765
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001766/**
1767 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1768 *
1769 * @param[in] pMe Decoder context
1770 * @param[out] pDecodedItem The decoded item that work is done on.
1771 *
1772 * @retval QCBOR_ERR_UNSUPPORTED
1773 * @retval QCBOR_ERR_HIT_END
1774 * @retval QCBOR_ERR_INT_OVERFLOW
1775 * @retval QCBOR_ERR_STRING_ALLOCATE
1776 * @retval QCBOR_ERR_STRING_TOO_LONG
1777 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001778 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001779 * @retval QCBOR_ERR_BAD_TYPE_7
1780 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1781 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1782 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1783 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1784 * @retval QCBOR_ERR_TOO_MANY_TAGS
1785 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1786 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1787 * @retval QCBOR_ERR_NO_MORE_ITEMS
1788 * @retval QCBOR_ERR_BAD_BREAK
1789 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1790 *
1791 * This handles the traversal descending into and asecnding out of
1792 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1793 * definite- and indefinte-length maps and arrays by looking at the
1794 * item count or finding CBOR breaks. It detects the ends of the
1795 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001796 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001797static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001798QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001799{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001800 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001801 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001802
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001803 /* If out of bytes to consume, it is either the end of the
1804 * top-level sequence of some bstr-wrapped CBOR that was entered.
1805 *
1806 * In the case of bstr-wrapped CBOR, the length of the
1807 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1808 * the bstr-wrapped CBOR is exited, the length is set back to the
1809 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001810 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001811 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001812 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001813 goto Done;
1814 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001815
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001816 /* Check to see if at the end of a bounded definite-length map or
1817 * array. The check for a break ending indefinite-length array is
1818 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001819 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001820 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001821 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001822 goto Done;
1823 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001824
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001825 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001826 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001827 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1828 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001829 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001830 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301831
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001832 /* Breaks ending arrays/maps are processed later in the call to
1833 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001834 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301835 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001836 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301837 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301838 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001839
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001840 /* Record the nesting level for this data item before processing
1841 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001842 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001843 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001844
Laurence Lundblade642282a2020-06-23 12:00:33 -07001845
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001846 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001847 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001848 /* If the new item is a map or array, descend.
1849 *
1850 * Empty indefinite-length maps and arrays are descended into,
1851 * but then ascended out of in the next chunk of code.
1852 *
1853 * Maps and arrays do count as items in the map/array that
1854 * encloses them so a decrement needs to be done for them too,
1855 * but that is done only when all the items in them have been
1856 * processed, not when they are opened with the exception of an
1857 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001858 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001859 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001860 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001861 pDecodedItem->uDataType,
1862 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001863 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001864 /* This error is probably a traversal error and it overrides
1865 * the non-traversal error.
1866 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001867 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001868 goto Done;
1869 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001870 }
1871
Laurence Lundblade02625d42020-06-25 14:41:41 -07001872 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1873 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1874 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001875 /* The following cases are handled here:
1876 * - A non-aggregate item like an integer or string
1877 * - An empty definite-length map or array
1878 * - An indefinite-length map or array that might be empty or might not.
1879 *
1880 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1881 * for an definite-length map/array and break detection for an
1882 * indefinite-0length map/array. If the end of the map/array was
1883 * reached, then it ascends nesting levels, possibly all the way
1884 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001885 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001886 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001887 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001888 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001889 /* This error is probably a traversal error and it overrides
1890 * the non-traversal error.
1891 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001892 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001893 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001894 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301895 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001896
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001897 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001898 /* Tell the caller what level is next. This tells them what
1899 * maps/arrays were closed out and makes it possible for them to
1900 * reconstruct the tree with just the information returned in a
1901 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001902 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001903 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001904 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001905 pDecodedItem->uNextNestLevel = 0;
1906 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001907 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001908 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001910Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001911 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001912}
1913
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001914
Laurence Lundblade37286c02022-09-03 10:05:02 -07001915#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001916/**
1917 * @brief Shift 0th tag out of the tag list.
1918 *
1919 * pDecodedItem[in,out] The data item to convert.
1920 *
1921 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1922 * shifted into empty slot at the end of the tag list.
1923 */
1924static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001925{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001926 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1927 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1928 }
1929 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001930}
1931
Laurence Lundblade37286c02022-09-03 10:05:02 -07001932#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001933
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001934/**
1935 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1936 *
1937 * pDecodedItem[in,out] The data item to convert.
1938 *
1939 * @retval QCBOR_ERR_DATE_OVERFLOW
1940 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001941 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001942 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001943 *
1944 * The epoch date tag defined in QCBOR allows for floating-point
1945 * dates. It even allows a protocol to flop between date formats when
1946 * ever it wants. Floating-point dates aren't that useful as they are
1947 * only needed for dates beyond the age of the earth.
1948 *
1949 * This converts all the date formats into one format of an unsigned
1950 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001952static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001953{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001954 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001956#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001958#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959
1960 switch (pDecodedItem->uDataType) {
1961
1962 case QCBOR_TYPE_INT64:
1963 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1964 break;
1965
1966 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001967 /* This only happens for CBOR type 0 > INT64_MAX so it is
1968 * always an overflow.
1969 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001970 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1971 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001972 break;
1973
1974 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001975 case QCBOR_TYPE_FLOAT:
1976#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001977 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001978 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001979 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001980 pDecodedItem->val.dfnum :
1981 (double)pDecodedItem->val.fnum;
1982
1983 /* The conversion from float to integer requires overflow
1984 * detection since floats can be much larger than integers.
1985 * This implementation errors out on these large float values
1986 * since they are beyond the age of the earth.
1987 *
1988 * These constants for the overflow check are computed by the
1989 * compiler. They are not computed at run time.
1990 *
1991 * The factor of 0x7ff is added/subtracted to avoid a
1992 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001993 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001994 * 64-bit integer has 63 bits of precision where a double
1995 * only has 53 bits. Without the 0x7ff factor, the compiler
1996 * may round up and produce a double for the bounds check
1997 * that is larger than can be stored in a 64-bit integer. The
1998 * amount of 0x7ff is picked because it has 11 bits set.
1999 *
2000 * Without the 0x7ff there is a ~30 minute range of time
2001 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002002 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002003 * generate a warning or error without the 0x7ff.
2004 */
2005 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2006 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2007
2008 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002009 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002010 goto Done;
2011 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002012
2013 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002015 pDecodedItem->val.epochDate.fSecondsFraction =
2016 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002017 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002018#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002019
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002020 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002021 goto Done;
2022
Laurence Lundblade9682a532020-06-06 18:33:04 -07002023#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024 break;
2025
2026 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002027 /* It's the arrays and maps that are unrecoverable because
2028 * they are not consumed here. Since this is just an error
2029 * condition, no extra code is added here to make the error
2030 * recoverable for non-arrays and maps like strings. */
2031 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002032 goto Done;
2033 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002034
Laurence Lundblade59289e52019-12-30 13:44:37 -08002035 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2036
2037Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002038 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039}
2040
2041
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002042/**
2043 * @brief Convert the days epoch date.
2044 *
2045 * pDecodedItem[in,out] The data item to convert.
2046 *
2047 * @retval QCBOR_ERR_DATE_OVERFLOW
2048 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002049 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002050 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002051 *
2052 * This is much simpler than the other epoch date format because
2053 * floating-porint is not allowed. This is mostly a simple type check.
2054 */
2055static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2056{
2057 QCBORError uReturn = QCBOR_SUCCESS;
2058
2059 switch (pDecodedItem->uDataType) {
2060
2061 case QCBOR_TYPE_INT64:
2062 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2063 break;
2064
2065 case QCBOR_TYPE_UINT64:
2066 /* This only happens for CBOR type 0 > INT64_MAX so it is
2067 * always an overflow.
2068 */
2069 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2070 goto Done;
2071 break;
2072
2073 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002074 /* It's the arrays and maps that are unrecoverable because
2075 * they are not consumed here. Since this is just an error
2076 * condition, no extra code is added here to make the error
2077 * recoverable for non-arrays and maps like strings. */
2078 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002079 goto Done;
2080 break;
2081 }
2082
2083 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2084
2085Done:
2086 return uReturn;
2087}
2088
2089
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002090#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002091
2092/* Forward declaration is necessary for
2093 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2094 * tags in the mantissa. If the mantissa is a decimal fraction or big
2095 * float in error, this will result in a recurive call to
2096 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2097 * correctly and the correct error is returned.
2098 */
2099static QCBORError
2100QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem);
2101
2102
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002103/**
2104 * @brief Decode decimal fractions and big floats.
2105 *
2106 * @param[in] pMe The decode context.
2107 * @param[in,out] pDecodedItem On input the array data item that
2108 * holds the mantissa and exponent. On
2109 * output the decoded mantissa and
2110 * exponent.
2111 *
2112 * @returns Decoding errors from getting primitive data items or
2113 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2114 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002115 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002116 * exponent and mantissa.
2117 *
2118 * This will fetch and decode the exponent and mantissa and put the
2119 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002120 *
2121 * This does no checking or processing of tag numbers. That is to be
2122 * done by the code that calls this.
2123 *
2124 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2125 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002126 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002127static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002128QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002129{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002130 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002131
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002132 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002133 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002134 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002135 goto Done;
2136 }
2137
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002138 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002139 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002140 * the nesting level the two integers must be at, which is one
2141 * deeper than that of the array.
2142 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002143 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2144
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002145 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002146 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002147 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2148 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002149 goto Done;
2150 }
2151 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002152 /* Array is empty or a map/array encountered when expecting an int */
2153 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002154 goto Done;
2155 }
2156 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002157 /* Data arriving as an unsigned int < INT64_MAX has been
2158 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2159 * also means that the only data arriving here of type
2160 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2161 * and thus an error that will get handled in the next else.
2162 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002163 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2164 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002165 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2166 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002167 goto Done;
2168 }
2169
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002170 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002171 QCBORItem mantissaItem;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002172 uReturn = QCBORDecode_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002173 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002174 goto Done;
2175 }
2176 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002177 /* Mantissa missing or map/array encountered when expecting number */
2178 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002179 goto Done;
2180 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002181 /* Stuff the mantissa data type into the item to send it up to the
2182 * the next level. */
2183 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002185 /* Data arriving as an unsigned int < INT64_MAX has been
2186 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2187 * also means that the only data arriving here of type
2188 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2189 * and thus an error that will get handled in an else below.
2190 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002191 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002192#ifndef QCBOR_DISABLE_TAGS
2193 /* With tags fully disabled a big number mantissa will error out
2194 * in the call to QCBORDecode_GetNextWithTags() because it has
2195 * a tag number.
2196 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002197 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2198 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002199 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002200 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002201#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002202 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002203 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2204 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002205 goto Done;
2206 }
2207
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002208 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002209 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002210 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002211 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002212 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002213 goto Done;
2214 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002215 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002216
2217Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002218 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002219}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002220#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002221
2222
Laurence Lundblade37286c02022-09-03 10:05:02 -07002223#ifndef QCBOR_DISABLE_TAGS
2224
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002225#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002226/**
2227 * @brief Decode the MIME type tag
2228 *
2229 * @param[in,out] pDecodedItem The item to decode.
2230 *
2231 * Handle the text and binary MIME type tags. Slightly too complicated
2232 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2233 * incorreclty text-only.
2234 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002235static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002236{
2237 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2238 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002239 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002240 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2241 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002242 /* It's the arrays and maps that are unrecoverable because
2243 * they are not consumed here. Since this is just an error
2244 * condition, no extra code is added here to make the error
2245 * recoverable for non-arrays and maps like strings. */
2246 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002247 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002248
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002249 return QCBOR_SUCCESS;
2250}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002251#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002252
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002253/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002254 * Table of CBOR tags whose content is either a text string or a byte
2255 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2256 * of uQCBORtype indicates the content should be a byte string rather
2257 * than a text string
2258 */
2259struct StringTagMapEntry {
2260 uint16_t uTagNumber;
2261 uint8_t uQCBORtype;
2262};
2263
2264#define IS_BYTE_STRING_BIT 0x80
2265#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2266
2267static const struct StringTagMapEntry StringTagMap[] = {
2268 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002269 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002270 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2271 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2272 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2273 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002274#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002275 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2276 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2277 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2278 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002279#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002280 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2281 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2282};
2283
2284
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002285/**
2286 * @brief Process standard CBOR tags whose content is a string
2287 *
2288 * @param[in] uTag The tag.
2289 * @param[in,out] pDecodedItem The data item.
2290 *
2291 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2292 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002293 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002294 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002295 * Process the CBOR tags that whose content is a byte string or a text
2296 * string and for which the string is just passed on to the caller.
2297 *
2298 * This maps the CBOR tag to the QCBOR type and checks the content
2299 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002300 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002301 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002302 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002303static inline QCBORError
2304ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002305{
Laurence Lundblade99615302020-11-29 11:19:47 -08002306 /* This only works on tags that were not mapped; no need for other yet */
2307 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2308 return QCBOR_ERR_UNSUPPORTED;
2309 }
2310
2311 unsigned uIndex;
2312 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2313 if(StringTagMap[uIndex].uTagNumber == uTag) {
2314 break;
2315 }
2316 }
2317
2318 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2319 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002320 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002321 return QCBOR_ERR_UNSUPPORTED;
2322 }
2323
2324 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2325 if(uQCBORType & IS_BYTE_STRING_BIT) {
2326 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2327 }
2328
2329 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002330 /* It's the arrays and maps that are unrecoverable because
2331 * they are not consumed here. Since this is just an error
2332 * condition, no extra code is added here to make the error
2333 * recoverable for non-arrays and maps like strings. */
2334 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002335 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002336
Laurence Lundblade99615302020-11-29 11:19:47 -08002337 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002338 return QCBOR_SUCCESS;
2339}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002340#endif /* QCBOR_DISABLE_TAGS */
2341
2342
2343#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2344/*
2345 * This returns the QCBOR_TYPE for a mantissa and exponent.
2346
2347Called in one context where there is always a tag
2348
2349 Called in another context where there might be a tag or the caller might say what they are expecting.
2350
2351 6 possible outputs
2352 */
2353static inline uint8_t
2354MantissaExponentDataType(const uint16_t uTagToProcess, const QCBORItem *pDecodedItem)
2355{
2356 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2357 QCBOR_TYPE_DECIMAL_FRACTION :
2358 QCBOR_TYPE_BIGFLOAT;
2359 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2360 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2361 }
2362 return uBase;
2363}
2364#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002365
2366
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002367/**
2368 * @brief Decode tag content for select tags (decoding layer 1).
2369 *
2370 * @param[in] pMe The decode context.
2371 * @param[out] pDecodedItem The decoded item.
2372 *
2373 * @return Decoding error code.
2374 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002375 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2376 * but the whole tag was not decoded. Here, the whole tags (tag number
2377 * and tag content) that are supported by QCBOR are decoded. This is a
2378 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002379 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002380static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002381QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002382{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002383 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002384
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002385 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002386 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002387 goto Done;
2388 }
2389
Laurence Lundblade37286c02022-09-03 10:05:02 -07002390#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002391 /* When there are no tag numbers for the item, this exits first
2392 * thing and effectively does nothing.
2393 *
2394 * This loops over all the tag numbers accumulated for this item
2395 * trying to decode and interpret them. This stops at the end of
2396 * the list or at the first tag number that can't be interpreted by
2397 * this code. This is effectively a recursive processing of the
2398 * tags number list that handles nested tags.
2399 */
2400 while(1) {
2401 /* Don't bother to unmap tags via QCBORITem.uTags since this
2402 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2403 */
2404 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002405
Laurence Lundblade99615302020-11-29 11:19:47 -08002406 if(uTagToProcess == CBOR_TAG_INVALID16) {
2407 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002408 break;
2409
Laurence Lundblade99615302020-11-29 11:19:47 -08002410 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002411 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002412
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002413 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2414 uReturn = DecodeDaysEpoch(pDecodedItem);
2415
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002416#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002417 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2418 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002419 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002420 /* --- Which is it, decimal fraction or a bigfloat? --- */
2421 pDecodedItem->uDataType = MantissaExponentDataType(uTagToProcess, pDecodedItem);
2422
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002423#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002424#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002425 } else if(uTagToProcess == CBOR_TAG_MIME ||
2426 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002427 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002428#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002429
Laurence Lundblade99615302020-11-29 11:19:47 -08002430 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002431 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002432 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002433
Laurence Lundblade99615302020-11-29 11:19:47 -08002434 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002435 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002436 * an unknown tag. This is the exit from the loop on the
2437 * first unknown tag. It is a successful exit.
2438 */
2439 uReturn = QCBOR_SUCCESS;
2440 break;
2441 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002442 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002443
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002444 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002445 /* Error exit from the loop */
2446 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002447 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002448
2449 /* A tag was successfully processed, shift it out of the list of
2450 * tags returned. This is the loop increment.
2451 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002452 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002453 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002454#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002455
2456Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002457 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002458}
2459
2460
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002461/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002462 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002463 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002464QCBORError
2465QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2466{
2467 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002468 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002469 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002470 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2471 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2472 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002473 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002474}
2475
2476
2477/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002478 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002479 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002480QCBORError
2481QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2482{
2483 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2484 const UsefulInputBuf Save = pMe->InBuf;
2485
2486 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2487
2488 pMe->nesting = SaveNesting;
2489 pMe->InBuf = Save;
2490
2491 return uErr;
2492}
2493
2494
2495/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002496 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002497 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002498void
2499QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2500{
2501 if(pMe->uLastError != QCBOR_SUCCESS) {
2502 return;
2503 }
2504
2505 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2506}
2507
2508
2509/*
2510 * Public function, see header qcbor/qcbor_decode.h file
2511 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002512void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2513{
2514 if(pMe->uLastError != QCBOR_SUCCESS) {
2515 return;
2516 }
2517
2518 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2519}
2520
2521
2522/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002523 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002524 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002525QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002526QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2527 QCBORItem *pDecodedItem,
2528 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002529{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002530#ifndef QCBOR_DISABLE_TAGS
2531
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002532 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002533
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002534 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2535 if(uReturn != QCBOR_SUCCESS) {
2536 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002537 }
2538
2539 if(pTags != NULL) {
2540 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002541 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002542 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2543 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002544 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002545 }
2546 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2547 return QCBOR_ERR_TOO_MANY_TAGS;
2548 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002549 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002550 pTags->uNumUsed++;
2551 }
2552 }
2553
2554 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002555
2556#else /* QCBOR_DISABLE_TAGS */
2557 (void)pMe;
2558 (void)pDecodedItem;
2559 (void)pTags;
2560 return QCBOR_ERR_TAGS_DISABLED;
2561#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002562}
2563
2564
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002565/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002566 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302567 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002568bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002569 const QCBORItem *pItem,
2570 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002571{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002572#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002573 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2574 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002575 break;
2576 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002577 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002578 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002579 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002580 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002581#else /* QCBOR_TAGS_DISABLED */
2582 (void)pMe;
2583 (void)pItem;
2584 (void)uTag;
2585#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002586
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002587 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002588}
2589
2590
2591/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002592 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002593 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002594QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002595{
Laurence Lundblade87495732021-02-26 10:05:55 -07002596 if(puConsumed != NULL) {
2597 *puConsumed = pMe->InBuf.cursor;
2598 }
2599
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002600 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002601
2602 if(uReturn != QCBOR_SUCCESS) {
2603 goto Done;
2604 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002605
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002606 /* Error out if all the maps/arrays are not closed out */
2607 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002608 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002609 goto Done;
2610 }
2611
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002612 /* Error out if not all the bytes are consumed */
2613 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002614 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002615 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002616
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002617Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002618 return uReturn;
2619}
2620
2621
2622/*
2623 * Public function, see header qcbor/qcbor_decode.h file
2624 */
2625QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2626{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002627#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002628 /* Call the destructor for the string allocator if there is one.
2629 * Always called, even if there are errors; always have to clean up.
2630 */
2631 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002632#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002633
Laurence Lundblade87495732021-02-26 10:05:55 -07002634 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002635}
2636
2637
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002638/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002639 * Public function, see header qcbor/qcbor_decode.h file
2640 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002641// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002642uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2643 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002644 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002645{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002646#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002647 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2648 return CBOR_TAG_INVALID64;
2649 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002650 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2651 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002652 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002653 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002654 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002655#else /* QCBOR_DISABLE_TAGS */
2656 (void)pMe;
2657 (void)pItem;
2658 (void)uIndex;
2659
2660 return CBOR_TAG_INVALID64;
2661#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002662}
2663
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002664
Laurence Lundblade9b334962020-08-27 10:55:53 -07002665/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002666 * Public function, see header qcbor/qcbor_decode.h file
2667 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002668uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2669 uint32_t uIndex)
2670{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002671#ifndef QCBOR_DISABLE_TAGS
2672
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002673 if(pMe->uLastError != QCBOR_SUCCESS) {
2674 return CBOR_TAG_INVALID64;
2675 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002676 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2677 return CBOR_TAG_INVALID64;
2678 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002679 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002680 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002681#else /* QCBOR_DISABLE_TAGS */
2682 (void)pMe;
2683 (void)uIndex;
2684
2685 return CBOR_TAG_INVALID64;
2686#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002687}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002689
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002690
2691
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002692#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002693
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002694/* ===========================================================================
2695 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002697 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002698 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2699 implements the function type QCBORStringAllocate and allows easy
2700 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002701
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002702 This particular allocator is built-in for convenience. The caller
2703 can implement their own. All of this following code will get
2704 dead-stripped if QCBORDecode_SetMemPool() is not called.
2705
2706 This is a very primitive memory allocator. It does not track
2707 individual allocations, only a high-water mark. A free or
2708 reallocation must be of the last chunk allocated.
2709
2710 The size of the pool and offset to free memory are packed into the
2711 first 8 bytes of the memory pool so we don't have to keep them in
2712 the decode context. Since the address of the pool may not be
2713 aligned, they have to be packed and unpacked as if they were
2714 serialized data of the wire or such.
2715
2716 The sizes packed in are uint32_t to be the same on all CPU types
2717 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002718 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002719
2720
Laurence Lundbladeee851742020-01-08 08:37:05 -08002721static inline int
2722MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002723{
2724 // Use of UsefulInputBuf is overkill, but it is convenient.
2725 UsefulInputBuf UIB;
2726
Laurence Lundbladeee851742020-01-08 08:37:05 -08002727 // Just assume the size here. It was checked during SetUp so
2728 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002729 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002730 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2731 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2732 return UsefulInputBuf_GetError(&UIB);
2733}
2734
2735
Laurence Lundbladeee851742020-01-08 08:37:05 -08002736static inline int
2737MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002738{
2739 // Use of UsefulOutBuf is overkill, but convenient. The
2740 // length check performed here is useful.
2741 UsefulOutBuf UOB;
2742
2743 UsefulOutBuf_Init(&UOB, Pool);
2744 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2745 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2746 return UsefulOutBuf_GetError(&UOB);
2747}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002748
2749
2750/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002751 Internal function for an allocation, reallocation free and destuct.
2752
2753 Having only one function rather than one each per mode saves space in
2754 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002755
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002756 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2757 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002758static UsefulBuf
2759MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002760{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002761 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002762
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002763 uint32_t uPoolSize;
2764 uint32_t uFreeOffset;
2765
2766 if(uNewSize > UINT32_MAX) {
2767 // This allocator is only good up to 4GB. This check should
2768 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2769 goto Done;
2770 }
2771 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2772
2773 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2774 goto Done;
2775 }
2776
2777 if(uNewSize) {
2778 if(pMem) {
2779 // REALLOCATION MODE
2780 // Calculate pointer to the end of the memory pool. It is
2781 // assumed that pPool + uPoolSize won't wrap around by
2782 // assuming the caller won't pass a pool buffer in that is
2783 // not in legitimate memory space.
2784 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2785
2786 // Check that the pointer for reallocation is in the range of the
2787 // pool. This also makes sure that pointer math further down
2788 // doesn't wrap under or over.
2789 if(pMem >= pPool && pMem < pPoolEnd) {
2790 // Offset to start of chunk for reallocation. This won't
2791 // wrap under because of check that pMem >= pPool. Cast
2792 // is safe because the pool is always less than UINT32_MAX
2793 // because of check in QCBORDecode_SetMemPool().
2794 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2795
2796 // Check to see if the allocation will fit. uPoolSize -
2797 // uMemOffset will not wrap under because of check that
2798 // pMem is in the range of the uPoolSize by check above.
2799 if(uNewSize <= uPoolSize - uMemOffset) {
2800 ReturnValue.ptr = pMem;
2801 ReturnValue.len = uNewSize;
2802
2803 // Addition won't wrap around over because uNewSize was
2804 // checked to be sure it is less than the pool size.
2805 uFreeOffset = uMemOffset + uNewSize32;
2806 }
2807 }
2808 } else {
2809 // ALLOCATION MODE
2810 // uPoolSize - uFreeOffset will not underflow because this
2811 // pool implementation makes sure uFreeOffset is always
2812 // smaller than uPoolSize through this check here and
2813 // reallocation case.
2814 if(uNewSize <= uPoolSize - uFreeOffset) {
2815 ReturnValue.len = uNewSize;
2816 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002817 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002818 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002819 }
2820 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002821 if(pMem) {
2822 // FREE MODE
2823 // Cast is safe because of limit on pool size in
2824 // QCBORDecode_SetMemPool()
2825 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2826 } else {
2827 // DESTRUCT MODE
2828 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002829 }
2830 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002831
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002832 UsefulBuf Pool = {pPool, uPoolSize};
2833 MemPool_Pack(Pool, uFreeOffset);
2834
2835Done:
2836 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002837}
2838
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002839
Laurence Lundbladef6531662018-12-04 10:42:22 +09002840/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002841 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002842 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002843QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2844 UsefulBuf Pool,
2845 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002846{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002847 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002848 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002849 // constant in the header is correct. This check should optimize
2850 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002851#ifdef _MSC_VER
2852#pragma warning(push)
2853#pragma warning(disable:4127) // conditional expression is constant
2854#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002855 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002856 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002857 }
Dave Thaler93c01182022-08-06 15:08:35 -04002858#ifdef _MSC_VER
2859#pragma warning(pop)
2860#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002861
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002862 // The pool size and free offset packed in to the beginning of pool
2863 // memory are only 32-bits. This check will optimize out on 32-bit
2864 // machines.
2865 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002866 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002867 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002868
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002869 // This checks that the pool buffer given is big enough.
2870 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002871 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002872 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002873
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002874 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002875
Laurence Lundblade30816f22018-11-10 13:40:22 +07002876 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002877}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002878#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002879
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002880
2881
Laurence Lundblade37286c02022-09-03 10:05:02 -07002882static inline void
2883CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002884{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002885#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002886 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002887#else
2888 (void)pMe;
2889 (void)pItem;
2890#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002891}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002892
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002893
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002894/**
2895 * @brief Consume an entire map or array including its contents.
2896 *
2897 * @param[in] pMe The decoder context.
2898 * @param[in] pItemToConsume The array/map whose contents are to be
2899 * consumed.
2900 * @param[out] puNextNestLevel The next nesting level after the item was
2901 * fully consumed.
2902 *
2903 * This may be called when @c pItemToConsume is not an array or
2904 * map. In that case, this is just a pass through for @c puNextNestLevel
2905 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002906 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002907static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002908ConsumeItem(QCBORDecodeContext *pMe,
2909 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002910 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002911{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002912 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002913 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002914
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002915 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002916 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2917
2918 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2919 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002920
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002921 /* This works for definite- and indefinite-length maps and
2922 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002923 */
2924 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002925 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002926 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2927 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002928 goto Done;
2929 }
2930 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002931
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002932 *puNextNestLevel = Item.uNextNestLevel;
2933
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002934 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002935
Laurence Lundblade1341c592020-04-11 14:19:05 -07002936 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002937 /* pItemToConsume is not a map or array. Just pass the nesting
2938 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002939 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2940
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002941 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002942 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002943
2944Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002945 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002946}
2947
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002948
2949void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2950{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002951 QCBORDecode_VGetNext(pMe, pDecodedItem);
2952
2953 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002954 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2955 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002956 }
2957}
2958
2959
2960
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002961/* Call only on maps and arrays. Rewinds the cursor
2962 * to the start as if it was just entered.
2963 */
2964static void RewindMapOrArray(QCBORDecodeContext *pMe)
2965{
2966 /* Reset nesting tracking to the deepest bounded level */
2967 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2968
2969 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2970
2971 /* Reposition traversal cursor to the start of the map/array */
2972 UsefulInputBuf_Seek(&(pMe->InBuf),
2973 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2974}
2975
2976
2977/*
2978 Public function, see header qcbor/qcbor_decode.h file
2979 */
2980void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2981{
2982 if(pMe->nesting.pCurrentBounded != NULL) {
2983 /* In a bounded map, array or bstr-wrapped CBOR */
2984
2985 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2986 /* In bstr-wrapped CBOR. */
2987
2988 /* Reposition traversal cursor to start of wrapping byte string */
2989 UsefulInputBuf_Seek(&(pMe->InBuf),
2990 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2991 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2992
2993 } else {
2994 /* In a map or array */
2995 RewindMapOrArray(pMe);
2996 }
2997
2998 } else {
2999 /* Not in anything bounded */
3000
3001 /* Reposition traversal cursor to the start of input CBOR */
3002 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3003
3004 /* Reset nesting tracking to beginning of input. */
3005 DecodeNesting_Init(&(pMe->nesting));
3006 }
3007
3008 pMe->uLastError = QCBOR_SUCCESS;
3009}
3010
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003011
Laurence Lundblade1341c592020-04-11 14:19:05 -07003012/* Return true if the labels in Item1 and Item2 are the same.
3013 Works only for integer and string labels. Returns false
3014 for any other type. */
3015static inline bool
3016MatchLabel(QCBORItem Item1, QCBORItem Item2)
3017{
3018 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
3019 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
3020 return true;
3021 }
3022 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003023 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003024 return true;
3025 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003026 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003027 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
3028 return true;
3029 }
3030 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
3031 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
3032 return true;
3033 }
3034 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003035
Laurence Lundblade1341c592020-04-11 14:19:05 -07003036 /* Other label types are never matched */
3037 return false;
3038}
3039
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003040
3041/*
3042 Returns true if Item1 and Item2 are the same type
3043 or if either are of QCBOR_TYPE_ANY.
3044 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003045static inline bool
3046MatchType(QCBORItem Item1, QCBORItem Item2)
3047{
3048 if(Item1.uDataType == Item2.uDataType) {
3049 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003050 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003051 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003052 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003053 return true;
3054 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003055 return false;
3056}
3057
3058
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003059/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003060 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003061
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003062 @param[in] pMe The decode context to search.
3063 @param[in,out] pItemArray The items to search for and the items found.
3064 @param[out] puOffset Byte offset of last item matched.
3065 @param[in] pCBContext Context for the not-found item call back.
3066 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003067
3068 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3069
Laurence Lundblade93d89472020-10-03 22:30:50 -07003070 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3071 were found for one of the labels being
3072 search for. This duplicate detection is
3073 only performed for items in pItemArray,
3074 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003075
Laurence Lundblade93d89472020-10-03 22:30:50 -07003076 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3077 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003078
3079 @retval Also errors returned by QCBORDecode_GetNext().
3080
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003081 On input pItemArray contains a list of labels and data types
3082 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003083
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003084 On output the fully retrieved items are filled in with
3085 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003086
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003087 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003088
3089 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003090 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003091static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003092MapSearch(QCBORDecodeContext *pMe,
3093 QCBORItem *pItemArray,
3094 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003095 void *pCBContext,
3096 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003098 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003099 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003100
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003101 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003102 uReturn = pMe->uLastError;
3103 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003104 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003105
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003106 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003107 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3108 /* QCBOR_TYPE_NONE as first item indicates just looking
3109 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003110 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3111 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003112 }
3113
Laurence Lundblade085d7952020-07-24 10:26:30 -07003114 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3115 // It is an empty bounded array or map
3116 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3117 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003118 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003119 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003120 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003121 // Nothing is ever found in an empty array or map. All items
3122 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003123 uReturn = QCBOR_SUCCESS;
3124 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003125 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003126 }
3127
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003128 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003129 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3130
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003131 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003132 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003133
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003134 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003135 Loop over all the items in the map or array. Each item
3136 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003137 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003138 length maps and arrays. The only reason this is ever
3139 called on arrays is to find their end position.
3140
3141 This will always run over all items in order to do
3142 duplicate detection.
3143
3144 This will exit with failure if it encounters an
3145 unrecoverable error, but continue on for recoverable
3146 errors.
3147
3148 If a recoverable error occurs on a matched item, then
3149 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003150 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003151 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003152 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003153 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003154 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003155 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003156
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003157 /* Get the item */
3158 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003159 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003160 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003161 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003162 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003163 goto Done;
3164 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003165 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003166 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003167 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003168 goto Done;
3169 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003170
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003171 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003172 bool bMatched = false;
3173 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3174 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003175 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003176 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3177 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003178 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003179 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003180 if(uResult != QCBOR_SUCCESS) {
3181 /* The label matches, but the data item is in error */
3182 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003183 goto Done;
3184 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003185 if(!MatchType(Item, pItemArray[nIndex])) {
3186 /* The data item is not of the type(s) requested */
3187 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003188 goto Done;
3189 }
3190
Laurence Lundblade1341c592020-04-11 14:19:05 -07003191 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003192 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003193 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003194 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003195 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003196 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003197 bMatched = true;
3198 }
3199 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003200
3201
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003202 if(!bMatched && pfCallback != NULL) {
3203 /*
3204 Call the callback on unmatched labels.
3205 (It is tempting to do duplicate detection here, but that would
3206 require dynamic memory allocation because the number of labels
3207 that might be encountered is unbounded.)
3208 */
3209 uReturn = (*pfCallback)(pCBContext, &Item);
3210 if(uReturn != QCBOR_SUCCESS) {
3211 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003212 }
3213 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003214
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003215 /*
3216 Consume the item whether matched or not. This
3217 does the work of traversing maps and array and
3218 everything in them. In this loop only the
3219 items at the current nesting level are examined
3220 to match the labels.
3221 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003222 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003223 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003224 goto Done;
3225 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003226
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003227 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003228
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003229 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003230
3231 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003232
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003233 // Check here makes sure that this won't accidentally be
3234 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003235 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003236 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3237 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003238 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3239 goto Done;
3240 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003241 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3242 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003243
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003244 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003245 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3246
3247 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003248 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003249 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003250 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003251 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3252 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003253 }
3254 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003255
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003256 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003257}
3258
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003259
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003260/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003261 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003262*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003263void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3264 int64_t nLabel,
3265 uint8_t uQcborType,
3266 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003267{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003268 if(pMe->uLastError != QCBOR_SUCCESS) {
3269 return;
3270 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003271
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003272 QCBORItem OneItemSeach[2];
3273 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3274 OneItemSeach[0].label.int64 = nLabel;
3275 OneItemSeach[0].uDataType = uQcborType;
3276 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003277
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003278 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003279
3280 *pItem = OneItemSeach[0];
3281
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003282 if(uReturn != QCBOR_SUCCESS) {
3283 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003284 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003285 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003286 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003287 }
3288
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003289 Done:
3290 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003291}
3292
3293
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003294/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003295 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003296*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003297void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3298 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003299 uint8_t uQcborType,
3300 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003301{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003302 if(pMe->uLastError != QCBOR_SUCCESS) {
3303 return;
3304 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003305
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003306 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003307 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3308 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3309 OneItemSeach[0].uDataType = uQcborType;
3310 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003311
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003312 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3313 if(uReturn != QCBOR_SUCCESS) {
3314 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003315 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003316 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003317 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003318 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003319 }
3320
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003321 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003322
3323Done:
3324 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003325}
3326
3327
Laurence Lundblade93d89472020-10-03 22:30:50 -07003328static QCBORError
3329CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003330{
3331 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3332 if(uDataType == puTypeList[i]) {
3333 return QCBOR_SUCCESS;
3334 }
3335 }
3336 return QCBOR_ERR_UNEXPECTED_TYPE;
3337}
3338
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003339
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003340/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003341 * Match a tag/type specification against the type of the item.
3342 *
3343 * @param[in] TagSpec Specification for matching tags.
3344 * @param[in] pItem The item to check.
3345 *
3346 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3347 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3348 *
3349 * This checks the item data type of untagged items as well as of
3350 * tagged items against a specification to see if decoding should
3351 * proceed.
3352 *
3353 * This relies on the automatic tag decoding done by QCBOR that turns
3354 * tag numbers into particular QCBOR_TYPEs so there is no actual
3355 * comparsion of tag numbers, just of QCBOR_TYPEs.
3356 *
3357 * This checks the data item type as possibly representing the tag
3358 * number or as the tag content type.
3359 *
3360 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3361 * data type against the allowed tag content types. It will also error out
3362 * if the caller tries to require a tag because there is no way that can
3363 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003364 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003365static QCBORError
3366CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003367{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003368 const int nItemType = pItem->uDataType;
3369 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3370
3371#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003372 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3373 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3374 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003375 * the caller has told us there should not be.
3376 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003377 return QCBOR_ERR_UNEXPECTED_TYPE;
3378 }
3379
Laurence Lundblade9b334962020-08-27 10:55:53 -07003380 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003381 /* Must match the tag number and only the tag */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003382 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3383 }
3384
3385 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3386 if(uReturn == QCBOR_SUCCESS) {
3387 return QCBOR_SUCCESS;
3388 }
3389
3390 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3391 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003392 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003393 return QCBOR_ERR_UNEXPECTED_TYPE;
3394 }
3395
Laurence Lundblade37286c02022-09-03 10:05:02 -07003396 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3397 * and it hasn't matched the content, so the end
3398 * result is whether it matches the tag. This is
3399 * the tag optional case that the CBOR standard discourages.
3400 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003401
3402 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003403
Laurence Lundblade37286c02022-09-03 10:05:02 -07003404#else /* QCBOR_DISABLE_TAGS */
3405 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3406 return QCBOR_ERR_UNEXPECTED_TYPE;
3407 }
3408
3409 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3410
3411#endif /* QCBOR_DISABLE_TAGS */
3412}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003413
Laurence Lundblade9b334962020-08-27 10:55:53 -07003414
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003415// This could be semi-private if need be
3416static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003417void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3418 const int64_t nLabel,
3419 const TagSpecification TagSpec,
3420 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003421{
3422 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3423 if(pMe->uLastError != QCBOR_SUCCESS) {
3424 return;
3425 }
3426
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003427 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003428}
3429
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003430
3431// This could be semi-private if need be
3432static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003433void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3434 const char *szLabel,
3435 const TagSpecification TagSpec,
3436 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003437{
3438 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3439 if(pMe->uLastError != QCBOR_SUCCESS) {
3440 return;
3441 }
3442
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003443 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003444}
3445
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003446// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003447void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3448 int64_t nLabel,
3449 TagSpecification TagSpec,
Laurence Lundblade37286c02022-09-03 10:05:02 -07003450 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003451{
3452 QCBORItem Item;
3453 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3454 if(pMe->uLastError == QCBOR_SUCCESS) {
3455 *pString = Item.val.string;
3456 }
3457}
3458
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003459// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003460void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3461 const char * szLabel,
3462 TagSpecification TagSpec,
3463 UsefulBufC *pString)
3464{
3465 QCBORItem Item;
3466 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3467 if(pMe->uLastError == QCBOR_SUCCESS) {
3468 *pString = Item.val.string;
3469 }
3470}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003471
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003472/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003473 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003474*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003475void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003476{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003477 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3478 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003479}
3480
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003481/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003482 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003483*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003484void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3485 QCBORItem *pItemList,
3486 void *pCallbackCtx,
3487 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003488{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003489 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3490 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003491}
3492
3493
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003494/**
3495 * @brief Search for a map/array by label and enter it
3496 *
3497 * @param[in] pMe The decode context.
3498 * @param[in] pSearch The map/array to search for.
3499 *
3500 * @c pSearch is expected to contain one item of type map or array
3501 * with the label specified. The current bounded map will be searched for
3502 * this and if found will be entered.
3503 *
3504 * If the label is not found, or the item found is not a map or array,
3505 * the error state is set.
3506 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003507static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003508{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003509 // The first item in pSearch is the one that is to be
3510 // entered. It should be the only one filled in. Any other
3511 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003512 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003513 return;
3514 }
3515
3516 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003517 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003518 if(pMe->uLastError != QCBOR_SUCCESS) {
3519 return;
3520 }
3521
Laurence Lundblade9b334962020-08-27 10:55:53 -07003522 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003523 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003524 return;
3525 }
3526
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003527
3528 /* The map or array was found. Now enter it.
3529 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003530 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3531 * next item for the pre-order traversal cursor to be the map/array
3532 * found by MapSearch(). The next few lines of code force the
3533 * cursor to that.
3534 *
3535 * There is no need to retain the old cursor because
3536 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3537 * beginning of the map/array being entered.
3538 *
3539 * The cursor is forced by: 1) setting the input buffer position to
3540 * the item offset found by MapSearch(), 2) setting the map/array
3541 * counter to the total in the map/array, 3) setting the nesting
3542 * level. Setting the map/array counter to the total is not
3543 * strictly correct, but this is OK because this cursor only needs
3544 * to be used to get one item and MapSearch() has already found it
3545 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003546 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003547 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003548
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003549 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3550
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003551 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003552
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003553 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003554}
3555
3556
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003557/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003558 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003559*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003560void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003561{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003562 QCBORItem OneItemSeach[2];
3563 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3564 OneItemSeach[0].label.int64 = nLabel;
3565 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3566 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003567
Laurence Lundblade9b334962020-08-27 10:55:53 -07003568 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003569 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003570}
3571
3572
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003573/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003574 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003575*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003576void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003577{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003578 QCBORItem OneItemSeach[2];
3579 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3580 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3581 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3582 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003583
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003584 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003585}
3586
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003587/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003588 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003589*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003590void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003591{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003592 QCBORItem OneItemSeach[2];
3593 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3594 OneItemSeach[0].label.int64 = nLabel;
3595 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3596 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003597
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003598 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003599}
3600
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003601/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003602 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003603*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003604void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3605{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003606 QCBORItem OneItemSeach[2];
3607 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3608 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3609 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3610 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003611
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003612 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003613}
3614
3615
Laurence Lundblade02625d42020-06-25 14:41:41 -07003616// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003617void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003618{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003619 QCBORError uErr;
3620
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003621 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003622 if(pMe->uLastError != QCBOR_SUCCESS) {
3623 // Already in error state; do nothing.
3624 return;
3625 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003626
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003627 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003628 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003629 uErr = QCBORDecode_GetNext(pMe, &Item);
3630 if(uErr != QCBOR_SUCCESS) {
3631 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003632 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003633 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003634 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3635 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003636 }
3637
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003638 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003639
3640
Laurence Lundbladef0499502020-08-01 11:55:57 -07003641 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003642 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003643 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3644 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003645 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003646 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3647 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003648 // Special case to increment nesting level for zero-length maps
3649 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003650 DecodeNesting_Descend(&(pMe->nesting), uType);
3651 }
3652
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003653 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003654
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003655 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3656 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003657
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003658 if(pItem != NULL) {
3659 *pItem = Item;
3660 }
3661
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003662Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003663 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003664}
3665
Laurence Lundblade02625d42020-06-25 14:41:41 -07003666
3667/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003668 This is the common work for exiting a level that is a bounded map,
3669 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003670
3671 One chunk of work is to set up the pre-order traversal so it is at
3672 the item just after the bounded map, array or bstr that is being
3673 exited. This is somewhat complex.
3674
3675 The other work is to level-up the bounded mode to next higest bounded
3676 mode or the top level if there isn't one.
3677 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003678static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003679ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003680{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003681 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003682
Laurence Lundblade02625d42020-06-25 14:41:41 -07003683 /*
3684 First the pre-order-traversal byte offset is positioned to the
3685 item just after the bounded mode item that was just consumed.
3686 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003687 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3688
Laurence Lundblade02625d42020-06-25 14:41:41 -07003689 /*
3690 Next, set the current nesting level to one above the bounded level
3691 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003692
Laurence Lundblade02625d42020-06-25 14:41:41 -07003693 DecodeNesting_CheckBoundedType() is always called before this and
3694 makes sure pCurrentBounded is valid.
3695 */
3696 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3697
3698 /*
3699 This does the complex work of leveling up the pre-order traversal
3700 when the end of a map or array or another bounded level is
3701 reached. It may do nothing, or ascend all the way to the top
3702 level.
3703 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003704 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003705 if(uErr != QCBOR_SUCCESS) {
3706 goto Done;
3707 }
3708
Laurence Lundblade02625d42020-06-25 14:41:41 -07003709 /*
3710 This makes the next highest bounded level the current bounded
3711 level. If there is no next highest level, then no bounded mode is
3712 in effect.
3713 */
3714 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003715
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003716 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003717
3718Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003719 return uErr;
3720}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003721
Laurence Lundblade02625d42020-06-25 14:41:41 -07003722
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003723// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003724void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003725{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003726 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003727 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003728 return;
3729 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003730
Laurence Lundblade02625d42020-06-25 14:41:41 -07003731 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003732
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003733 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003734 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003735 goto Done;
3736 }
3737
Laurence Lundblade02625d42020-06-25 14:41:41 -07003738 /*
3739 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003740 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003741 from previous map search, then do a dummy search.
3742 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003743 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003744 QCBORItem Dummy;
3745 Dummy.uLabelType = QCBOR_TYPE_NONE;
3746 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3747 if(uErr != QCBOR_SUCCESS) {
3748 goto Done;
3749 }
3750 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003751
Laurence Lundblade02625d42020-06-25 14:41:41 -07003752 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003753
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003754Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003755 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003756}
3757
3758
Laurence Lundblade1341c592020-04-11 14:19:05 -07003759
Laurence Lundblade37286c02022-09-03 10:05:02 -07003760static QCBORError
3761InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
3762 const QCBORItem *pItem,
3763 const uint8_t uTagRequirement,
3764 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003765{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003766 if(pBstr) {
3767 *pBstr = NULLUsefulBufC;
3768 }
3769
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003770 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003771 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003772 return pMe->uLastError;
3773 }
3774
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003775 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003776
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003777 const TagSpecification TagSpec =
3778 {
3779 uTagRequirement,
3780 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3781 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3782 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003783
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003784 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003785 if(uError != QCBOR_SUCCESS) {
3786 goto Done;
3787 }
3788
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003789 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003790 /* Reverse the decrement done by GetNext() for the bstr so the
3791 * increment in QCBORDecode_NestLevelAscender() called by
3792 * ExitBoundedLevel() will work right.
3793 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003794 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003795 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003796
3797 if(pBstr) {
3798 *pBstr = pItem->val.string;
3799 }
3800
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003801 /* This saves the current length of the UsefulInputBuf and then
3802 * narrows the UsefulInputBuf to start and length of the wrapped
3803 * CBOR that is being entered.
3804 *
3805 * Most of these calls are simple inline accessors so this doesn't
3806 * amount to much code.
3807 */
3808
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003809 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003810 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3811 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003812 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003813 goto Done;
3814 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003815
3816 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3817 pItem->val.string.ptr);
3818 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3819 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3820 /* This should never happen because pItem->val.string.ptr should
3821 * always be valid since it was just returned.
3822 */
3823 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3824 goto Done;
3825 }
3826
3827 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3828
3829 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003830 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003831
Laurence Lundblade02625d42020-06-25 14:41:41 -07003832 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003833 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003834 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003835Done:
3836 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003837}
3838
3839
Laurence Lundblade02625d42020-06-25 14:41:41 -07003840/*
3841 Public function, see header qcbor/qcbor_decode.h file
3842 */
3843void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003844 uint8_t uTagRequirement,
3845 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003846{
3847 if(pMe->uLastError != QCBOR_SUCCESS) {
3848 // Already in error state; do nothing.
3849 return;
3850 }
3851
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003852 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003853 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003854 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3855 if(pMe->uLastError != QCBOR_SUCCESS) {
3856 return;
3857 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003858
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003859 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003860 &Item,
3861 uTagRequirement,
3862 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003863}
3864
3865
Laurence Lundblade02625d42020-06-25 14:41:41 -07003866/*
3867 Public function, see header qcbor/qcbor_decode.h file
3868 */
3869void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003870 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003871 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003872 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003873{
3874 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003875 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003876
Laurence Lundblade93d89472020-10-03 22:30:50 -07003877 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3878 &Item,
3879 uTagRequirement,
3880 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003881}
3882
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003883
Laurence Lundblade02625d42020-06-25 14:41:41 -07003884/*
3885 Public function, see header qcbor/qcbor_decode.h file
3886 */
3887void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003888 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003889 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003890 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003891{
3892 QCBORItem Item;
3893 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3894
Laurence Lundblade93d89472020-10-03 22:30:50 -07003895 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3896 &Item,
3897 uTagRequirement,
3898 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003899}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003900
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003901
Laurence Lundblade02625d42020-06-25 14:41:41 -07003902/*
3903 Public function, see header qcbor/qcbor_decode.h file
3904 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003905void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003906{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003907 if(pMe->uLastError != QCBOR_SUCCESS) {
3908 // Already in error state; do nothing.
3909 return;
3910 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003911
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003912 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003913 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003914 return;
3915 }
3916
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003917 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3918
Laurence Lundblade02625d42020-06-25 14:41:41 -07003919 /*
3920 Reset the length of the UsefulInputBuf to what it was before
3921 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003922 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003923 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003924 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003925
3926
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003927 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003928 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003929}
3930
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003931
Laurence Lundbladee6430642020-03-14 21:15:44 -07003932
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003933
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003934static inline void
3935ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003936{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003937 if(pMe->uLastError != QCBOR_SUCCESS) {
3938 /* Already in error state, do nothing */
3939 return;
3940 }
3941
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003942 switch(pItem->uDataType) {
3943 case QCBOR_TYPE_TRUE:
3944 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003945 break;
3946
3947 case QCBOR_TYPE_FALSE:
3948 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003949 break;
3950
3951 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003952 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003953 break;
3954 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003955 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003956}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003958
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003959/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003960 * Public function, see header qcbor/qcbor_decode.h file
3961 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003962void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003963{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003964 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003965 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966 return;
3967 }
3968
Laurence Lundbladec4537442020-04-14 18:53:22 -07003969 QCBORItem Item;
3970
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003971 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3972
3973 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003974}
3975
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003976
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003977/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003978 * Public function, see header qcbor/qcbor_decode.h file
3979 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003980void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003981{
3982 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003983 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003984
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003985 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003986}
3987
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003988
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003989/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003990 * Public function, see header qcbor/qcbor_decode.h file
3991 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003992void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3993{
3994 QCBORItem Item;
3995 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3996
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003997 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003998}
3999
4000
4001
Laurence Lundbladec7114722020-08-13 05:11:40 -07004002
4003static void ProcessEpochDate(QCBORDecodeContext *pMe,
4004 QCBORItem *pItem,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004005 const uint8_t uTagRequirement,
Laurence Lundbladec7114722020-08-13 05:11:40 -07004006 int64_t *pnTime)
4007{
4008 if(pMe->uLastError != QCBOR_SUCCESS) {
4009 // Already in error state, do nothing
4010 return;
4011 }
4012
4013 QCBORError uErr;
4014
4015 const TagSpecification TagSpec =
4016 {
4017 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004018 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4019 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004020 };
4021
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004022 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004023 if(uErr != QCBOR_SUCCESS) {
4024 goto Done;
4025 }
4026
4027 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
4028 uErr = DecodeDateEpoch(pItem);
4029 if(uErr != QCBOR_SUCCESS) {
4030 goto Done;
4031 }
4032 }
4033
Laurence Lundblade9b334962020-08-27 10:55:53 -07004034 // Save the tags in the last item's tags in the decode context
4035 // for QCBORDecode_GetNthTagOfLast()
4036 CopyTags(pMe, pItem);
4037
Laurence Lundbladec7114722020-08-13 05:11:40 -07004038 *pnTime = pItem->val.epochDate.nSeconds;
4039
4040Done:
4041 pMe->uLastError = (uint8_t)uErr;
4042}
4043
4044
4045void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004046 uint8_t uTagRequirement,
4047 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004048{
4049 if(pMe->uLastError != QCBOR_SUCCESS) {
4050 // Already in error state, do nothing
4051 return;
4052 }
4053
4054 QCBORItem Item;
4055 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4056
4057 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4058}
4059
4060
4061void
4062QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4063 int64_t nLabel,
4064 uint8_t uTagRequirement,
4065 int64_t *pnTime)
4066{
4067 QCBORItem Item;
4068 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4069 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4070}
4071
4072
4073void
4074QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4075 const char *szLabel,
4076 uint8_t uTagRequirement,
4077 int64_t *pnTime)
4078{
4079 QCBORItem Item;
4080 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4081 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4082}
4083
4084
4085
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004086/*
4087 * Common processing for the RFC 8943 day-count tag. Mostly
4088 * make sure the tag content is correct and copy forward any
4089 * further other tag numbers.
4090 */
4091static void ProcessEpochDays(QCBORDecodeContext *pMe,
4092 QCBORItem *pItem,
4093 uint8_t uTagRequirement,
4094 int64_t *pnDays)
4095{
4096 if(pMe->uLastError != QCBOR_SUCCESS) {
4097 /* Already in error state, do nothing */
4098 return;
4099 }
4100
4101 QCBORError uErr;
4102
4103 const TagSpecification TagSpec =
4104 {
4105 uTagRequirement,
4106 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4107 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4108 };
4109
4110 uErr = CheckTagRequirement(TagSpec, pItem);
4111 if(uErr != QCBOR_SUCCESS) {
4112 goto Done;
4113 }
4114
4115 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
4116 uErr = DecodeDaysEpoch(pItem);
4117 if(uErr != QCBOR_SUCCESS) {
4118 goto Done;
4119 }
4120 }
4121
4122 /* Save the tags in the last item's tags in the decode context
4123 * for QCBORDecode_GetNthTagOfLast()
4124 */
4125 CopyTags(pMe, pItem);
4126
4127 *pnDays = pItem->val.epochDays;
4128
4129Done:
4130 pMe->uLastError = (uint8_t)uErr;
4131}
4132
4133
4134/*
4135 * Public function, see header qcbor/qcbor_decode.h
4136 */
4137void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4138 uint8_t uTagRequirement,
4139 int64_t *pnDays)
4140{
4141 if(pMe->uLastError != QCBOR_SUCCESS) {
4142 /* Already in error state, do nothing */
4143 return;
4144 }
4145
4146 QCBORItem Item;
4147 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4148
4149 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4150}
4151
4152
4153/*
4154 * Public function, see header qcbor/qcbor_decode.h
4155 */
4156void
4157QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4158 int64_t nLabel,
4159 uint8_t uTagRequirement,
4160 int64_t *pnDays)
4161{
4162 QCBORItem Item;
4163 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4164 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4165}
4166
4167
4168/*
4169 * Public function, see header qcbor/qcbor_decode.h
4170 */
4171void
4172QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4173 const char *szLabel,
4174 uint8_t uTagRequirement,
4175 int64_t *pnDays)
4176{
4177 QCBORItem Item;
4178 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4179 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4180}
4181
4182
4183
Laurence Lundblade37286c02022-09-03 10:05:02 -07004184/*
4185 * @brief Get a string that matches the type/tag specification.
4186 */
4187void
4188QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4189 const TagSpecification TagSpec,
4190 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004191{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004192 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004193 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004194 return;
4195 }
4196
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004197 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004198 QCBORItem Item;
4199
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004200 uError = QCBORDecode_GetNext(pMe, &Item);
4201 if(uError != QCBOR_SUCCESS) {
4202 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004203 return;
4204 }
4205
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004206 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004207
4208 if(pMe->uLastError == QCBOR_SUCCESS) {
4209 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004210 } else {
4211 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004212 }
4213}
4214
Laurence Lundbladec4537442020-04-14 18:53:22 -07004215
4216
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004217
Laurence Lundblade37286c02022-09-03 10:05:02 -07004218static QCBORError
4219ProcessBigNum(const uint8_t uTagRequirement,
4220 const QCBORItem *pItem,
4221 UsefulBufC *pValue,
4222 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004223{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004224 const TagSpecification TagSpec =
4225 {
4226 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004227 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4228 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004229 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004230
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004231 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004232 if(uErr != QCBOR_SUCCESS) {
4233 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004235
4236 *pValue = pItem->val.string;
4237
4238 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4239 *pbIsNegative = false;
4240 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4241 *pbIsNegative = true;
4242 }
4243
4244 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004245}
4246
4247
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004248/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004249 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004250 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004251void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4252 uint8_t uTagRequirement,
4253 UsefulBufC *pValue,
4254 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004255{
4256 if(pMe->uLastError != QCBOR_SUCCESS) {
4257 // Already in error state, do nothing
4258 return;
4259 }
4260
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004261 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004262 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4263 if(uError != QCBOR_SUCCESS) {
4264 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004265 return;
4266 }
4267
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004268 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004269}
4270
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004271
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004272/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004273 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004274*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004275void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4276 int64_t nLabel,
4277 uint8_t uTagRequirement,
4278 UsefulBufC *pValue,
4279 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004280{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004281 QCBORItem Item;
4282 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004283 if(pMe->uLastError != QCBOR_SUCCESS) {
4284 return;
4285 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004286
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004287 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004288}
4289
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004290
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004291/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004292 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004293*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004294void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4295 const char *szLabel,
4296 uint8_t uTagRequirement,
4297 UsefulBufC *pValue,
4298 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004299{
4300 QCBORItem Item;
4301 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004302 if(pMe->uLastError != QCBOR_SUCCESS) {
4303 return;
4304 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004305
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004306 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004307}
4308
4309
4310
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004311
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004312// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004313QCBORError
4314QCBORDecode_GetMIMEInternal(const uint8_t uTagRequirement,
4315 const QCBORItem *pItem,
4316 UsefulBufC *pMessage,
4317 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004318{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004319 const TagSpecification TagSpecText =
4320 {
4321 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004322 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4323 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004324 };
4325 const TagSpecification TagSpecBinary =
4326 {
4327 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004328 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4329 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004330 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004331
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004332 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004333
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004334 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004335 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004336 if(pbIsTag257 != NULL) {
4337 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004338 }
4339 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004340 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004341 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004342 if(pbIsTag257 != NULL) {
4343 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004344 }
4345 uReturn = QCBOR_SUCCESS;
4346
4347 } else {
4348 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4349 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004350
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004351 return uReturn;
4352}
4353
Laurence Lundblade93d89472020-10-03 22:30:50 -07004354// Improvement: add methods for wrapped CBOR, a simple alternate
4355// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004356
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004357
4358
4359
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004360#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004361
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004362typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004363
4364
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004365// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004366static QCBORError
4367Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004368{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004369 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004370
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004371 if(uResult != 0) {
4372 /* This loop will run a maximum of 19 times because
4373 * UINT64_MAX < 10 ^^ 19. More than that will cause
4374 * exit with the overflow error
4375 */
4376 for(; nExponent > 0; nExponent--) {
4377 if(uResult > UINT64_MAX / 10) {
4378 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4379 }
4380 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004381 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004382
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004383 for(; nExponent < 0; nExponent++) {
4384 uResult = uResult / 10;
4385 if(uResult == 0) {
4386 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4387 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004388 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004389 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004390 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391
4392 *puResult = uResult;
4393
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004394 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395}
4396
4397
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004398// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004399static QCBORError
4400Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004401{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004402 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004403
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004404 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004405
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004406 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004407 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004408 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004409 */
4410 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004411 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004412 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004413 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004414 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004415 nExponent--;
4416 }
4417
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004418 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004419 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004420 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4421 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004422 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004423 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004424 }
4425
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004426 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004427
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004428 return QCBOR_SUCCESS;
4429}
4430
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004431
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004432/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004433 Compute value with signed mantissa and signed result. Works with
4434 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004435 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004436static inline QCBORError ExponentiateNN(int64_t nMantissa,
4437 int64_t nExponent,
4438 int64_t *pnResult,
4439 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004440{
4441 uint64_t uResult;
4442
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004443 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004444 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004445 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4446
4447 // Do the exponentiation of the positive mantissa
4448 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4449 if(uReturn) {
4450 return uReturn;
4451 }
4452
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004453
Laurence Lundblade983500d2020-05-14 11:49:34 -07004454 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4455 of INT64_MIN. This assumes two's compliment representation where
4456 INT64_MIN is one increment farther from 0 than INT64_MAX.
4457 Trying to write -INT64_MIN doesn't work to get this because the
4458 compiler tries to work with an int64_t which can't represent
4459 -INT64_MIN.
4460 */
4461 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4462
4463 // Error out if too large
4464 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004465 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4466 }
4467
4468 // Casts are safe because of checks above
4469 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4470
4471 return QCBOR_SUCCESS;
4472}
4473
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004474
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004475/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004476 Compute value with signed mantissa and unsigned result. Works with
4477 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004478 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004479static inline QCBORError ExponentitateNU(int64_t nMantissa,
4480 int64_t nExponent,
4481 uint64_t *puResult,
4482 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004483{
4484 if(nMantissa < 0) {
4485 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4486 }
4487
4488 // Cast to unsigned is OK because of check for negative
4489 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4490 // Exponentiation is straight forward
4491 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4492}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004493
4494
4495/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004496 Compute value with signed mantissa and unsigned result. Works with
4497 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004498 */
4499static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4500 int64_t nExponent,
4501 uint64_t *puResult,
4502 fExponentiator pfExp)
4503{
4504 return (*pfExp)(uMantissa, nExponent, puResult);
4505}
4506
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004507#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004508
4509
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004510
4511
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004512
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004513static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004514{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004515 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004516
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004517 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004518 const uint8_t *pByte = BigNum.ptr;
4519 size_t uLen = BigNum.len;
4520 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004521 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004522 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004523 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004524 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004525 }
4526
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004527 *pResult = uResult;
4528 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004529}
4530
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004531
Laurence Lundblade887add82020-05-17 05:50:34 -07004532static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004533{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004534 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004535}
4536
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004537
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004538static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004539{
4540 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004541 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4542 if(uError) {
4543 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004544 }
4545 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4546 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004547 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004548}
4549
4550
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004551static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004552{
4553 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004554 /* The negative integer furthest from zero for a C int64_t is
4555 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4556 negative number in CBOR is computed as -n - 1 where n is the
4557 encoded integer, where n is what is in the variable BigNum. When
4558 converting BigNum to a uint64_t, the maximum value is thus
4559 INT64_MAX, so that when it -n - 1 is applied to it the result will
4560 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004561
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004562 -n - 1 <= INT64_MIN.
4563 -n - 1 <= -INT64_MAX - 1
4564 n <= INT64_MAX.
4565 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004566 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004567 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004568 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004569 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004570
4571 /// Now apply -n - 1. The cast is safe because
4572 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4573 // is the largest positive integer that an int64_t can
4574 // represent. */
4575 *pnResult = -(int64_t)uResult - 1;
4576
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004577 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004578}
4579
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004580
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004581
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004582
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004583
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004585Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004586
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004587\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588
Laurence Lundblade93d89472020-10-03 22:30:50 -07004589\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4590 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591
4592\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4593
Laurence Lundblade93d89472020-10-03 22:30:50 -07004594\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4595 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004596*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004597static QCBORError
4598ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004599{
4600 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004601 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004602 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004603#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004604 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004605 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4606 http://www.cplusplus.com/reference/cmath/llround/
4607 */
4608 // Not interested in FE_INEXACT
4609 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004610 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4611 *pnValue = llround(pItem->val.dfnum);
4612 } else {
4613 *pnValue = lroundf(pItem->val.fnum);
4614 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004615 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4616 // llround() shouldn't result in divide by zero, but catch
4617 // it here in case it unexpectedly does. Don't try to
4618 // distinguish between the various exceptions because it seems
4619 // they vary by CPU, compiler and OS.
4620 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004621 }
4622 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004623 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004624 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004625#else
4626 return QCBOR_ERR_HW_FLOAT_DISABLED;
4627#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004628 break;
4629
4630 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004632 *pnValue = pItem->val.int64;
4633 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004634 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004635 }
4636 break;
4637
4638 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004639 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004640 if(pItem->val.uint64 < INT64_MAX) {
4641 *pnValue = pItem->val.int64;
4642 } else {
4643 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4644 }
4645 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004646 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004647 }
4648 break;
4649
4650 default:
4651 return QCBOR_ERR_UNEXPECTED_TYPE;
4652 }
4653 return QCBOR_SUCCESS;
4654}
4655
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004657void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004658 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004659 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004660 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004661{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004662 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004663 return;
4664 }
4665
Laurence Lundbladee6430642020-03-14 21:15:44 -07004666 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004667 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4668 if(uError) {
4669 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004670 return;
4671 }
4672
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004673 if(pItem) {
4674 *pItem = Item;
4675 }
4676
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004677 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004678}
4679
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004681void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4682 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004683 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004684 int64_t *pnValue,
4685 QCBORItem *pItem)
4686{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004687 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004688 if(pMe->uLastError != QCBOR_SUCCESS) {
4689 return;
4690 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004691
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004692 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004693}
4694
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004695
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004696void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4697 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004699 int64_t *pnValue,
4700 QCBORItem *pItem)
4701{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004702 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004703 if(pMe->uLastError != QCBOR_SUCCESS) {
4704 return;
4705 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004706
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004707 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004708}
4709
4710
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711/*
4712 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004713
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004715
Laurence Lundblade93d89472020-10-03 22:30:50 -07004716 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4717 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718
4719 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4720
Laurence Lundblade93d89472020-10-03 22:30:50 -07004721 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4722 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004724static QCBORError
4725Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004726{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004727 switch(pItem->uDataType) {
4728
4729 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004730 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004731 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004732 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004733 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004734 }
4735 break;
4736
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004737 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004738 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004739 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004740 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004742 }
4743 break;
4744
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004745#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004746 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004747 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004748 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004749 pItem->val.expAndMantissa.nExponent,
4750 pnValue,
4751 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004752 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004753 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004754 }
4755 break;
4756
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004757 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004758 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004759 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004760 pItem->val.expAndMantissa.nExponent,
4761 pnValue,
4762 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004763 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004765 }
4766 break;
4767
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004768 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004769 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004770 int64_t nMantissa;
4771 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004772 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4773 if(uErr) {
4774 return uErr;
4775 }
4776 return ExponentiateNN(nMantissa,
4777 pItem->val.expAndMantissa.nExponent,
4778 pnValue,
4779 Exponentitate10);
4780 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004781 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004782 }
4783 break;
4784
4785 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004787 int64_t nMantissa;
4788 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004789 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4790 if(uErr) {
4791 return uErr;
4792 }
4793 return ExponentiateNN(nMantissa,
4794 pItem->val.expAndMantissa.nExponent,
4795 pnValue,
4796 Exponentitate10);
4797 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004798 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004799 }
4800 break;
4801
4802 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004803 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004804 int64_t nMantissa;
4805 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004806 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4807 if(uErr) {
4808 return uErr;
4809 }
4810 return ExponentiateNN(nMantissa,
4811 pItem->val.expAndMantissa.nExponent,
4812 pnValue,
4813 Exponentitate2);
4814 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004815 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004816 }
4817 break;
4818
4819 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004820 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004821 int64_t nMantissa;
4822 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004823 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4824 if(uErr) {
4825 return uErr;
4826 }
4827 return ExponentiateNN(nMantissa,
4828 pItem->val.expAndMantissa.nExponent,
4829 pnValue,
4830 Exponentitate2);
4831 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004833 }
4834 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004835#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004836
Laurence Lundbladee6430642020-03-14 21:15:44 -07004837
Laurence Lundbladec4537442020-04-14 18:53:22 -07004838 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004839 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004840}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841
4842
Laurence Lundbladec4537442020-04-14 18:53:22 -07004843/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004844 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004845 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004846void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004847{
4848 QCBORItem Item;
4849
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004850 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004851
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004852 if(pMe->uLastError == QCBOR_SUCCESS) {
4853 // The above conversion succeeded
4854 return;
4855 }
4856
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004857 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004858 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004859 return;
4860 }
4861
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004863}
4864
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865
4866/*
4867Public function, see header qcbor/qcbor_decode.h file
4868*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004869void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4870 int64_t nLabel,
4871 uint32_t uConvertTypes,
4872 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004873{
4874 QCBORItem Item;
4875
Laurence Lundblade93d89472020-10-03 22:30:50 -07004876 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4877 nLabel,
4878 uConvertTypes,
4879 pnValue,
4880 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004881
4882 if(pMe->uLastError == QCBOR_SUCCESS) {
4883 // The above conversion succeeded
4884 return;
4885 }
4886
4887 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4888 // The above conversion failed in a way that code below can't correct
4889 return;
4890 }
4891
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004892 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004893}
4894
4895
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004896/*
4897Public function, see header qcbor/qcbor_decode.h file
4898*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004899void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4900 const char *szLabel,
4901 uint32_t uConvertTypes,
4902 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004903{
4904 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004905 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4906 szLabel,
4907 uConvertTypes,
4908 pnValue,
4909 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004910
4911 if(pMe->uLastError == QCBOR_SUCCESS) {
4912 // The above conversion succeeded
4913 return;
4914 }
4915
4916 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4917 // The above conversion failed in a way that code below can't correct
4918 return;
4919 }
4920
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004921 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004922}
4923
4924
Laurence Lundblade93d89472020-10-03 22:30:50 -07004925static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926{
4927 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004928 case QCBOR_TYPE_DOUBLE:
4929 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004930#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004931 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004932 // Can't use llround here because it will not convert values
4933 // greater than INT64_MAX and less than UINT64_MAX that
4934 // need to be converted so it is more complicated.
4935 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4936 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4937 if(isnan(pItem->val.dfnum)) {
4938 return QCBOR_ERR_FLOAT_EXCEPTION;
4939 } else if(pItem->val.dfnum < 0) {
4940 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4941 } else {
4942 double dRounded = round(pItem->val.dfnum);
4943 // See discussion in DecodeDateEpoch() for
4944 // explanation of - 0x7ff
4945 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4946 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4947 }
4948 *puValue = (uint64_t)dRounded;
4949 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004950 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004951 if(isnan(pItem->val.fnum)) {
4952 return QCBOR_ERR_FLOAT_EXCEPTION;
4953 } else if(pItem->val.fnum < 0) {
4954 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4955 } else {
4956 float fRounded = roundf(pItem->val.fnum);
4957 // See discussion in DecodeDateEpoch() for
4958 // explanation of - 0x7ff
4959 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4960 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4961 }
4962 *puValue = (uint64_t)fRounded;
4963 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004964 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004965 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4966 // round() and roundf() shouldn't result in exceptions here, but
4967 // catch them to be robust and thorough. Don't try to
4968 // distinguish between the various exceptions because it seems
4969 // they vary by CPU, compiler and OS.
4970 return QCBOR_ERR_FLOAT_EXCEPTION;
4971 }
4972
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004973 } else {
4974 return QCBOR_ERR_UNEXPECTED_TYPE;
4975 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004976#else
4977 return QCBOR_ERR_HW_FLOAT_DISABLED;
4978#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004979 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004980
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004981 case QCBOR_TYPE_INT64:
4982 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4983 if(pItem->val.int64 >= 0) {
4984 *puValue = (uint64_t)pItem->val.int64;
4985 } else {
4986 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4987 }
4988 } else {
4989 return QCBOR_ERR_UNEXPECTED_TYPE;
4990 }
4991 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004992
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004993 case QCBOR_TYPE_UINT64:
4994 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4995 *puValue = pItem->val.uint64;
4996 } else {
4997 return QCBOR_ERR_UNEXPECTED_TYPE;
4998 }
4999 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005000
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005001 default:
5002 return QCBOR_ERR_UNEXPECTED_TYPE;
5003 }
5004
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005005 return QCBOR_SUCCESS;
5006}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005007
5008
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005009void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005010 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005011 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005012 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005013{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005014 if(pMe->uLastError != QCBOR_SUCCESS) {
5015 return;
5016 }
5017
Laurence Lundbladec4537442020-04-14 18:53:22 -07005018 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005019
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005020 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5021 if(uError) {
5022 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005023 return;
5024 }
5025
Laurence Lundbladea826c502020-05-10 21:07:00 -07005026 if(pItem) {
5027 *pItem = Item;
5028 }
5029
Laurence Lundblade93d89472020-10-03 22:30:50 -07005030 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005031}
5032
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005033
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005034void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005035 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005036 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005037 uint64_t *puValue,
5038 QCBORItem *pItem)
5039{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005040 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005041 if(pMe->uLastError != QCBOR_SUCCESS) {
5042 return;
5043 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005044
Laurence Lundblade93d89472020-10-03 22:30:50 -07005045 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005046}
5047
5048
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005049void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005050 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005051 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005052 uint64_t *puValue,
5053 QCBORItem *pItem)
5054{
5055 if(pMe->uLastError != QCBOR_SUCCESS) {
5056 return;
5057 }
5058
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005059 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005060 if(pMe->uLastError != QCBOR_SUCCESS) {
5061 return;
5062 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005063
Laurence Lundblade93d89472020-10-03 22:30:50 -07005064 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005065}
5066
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005067
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005068
Laurence Lundblade93d89472020-10-03 22:30:50 -07005069static QCBORError
5070UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005071{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005072 switch(pItem->uDataType) {
5073
5074 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005075 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005076 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
5077 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005078 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005079 }
5080 break;
5081
5082 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005083 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005084 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5085 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005086 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005087 }
5088 break;
5089
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005090#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005091
5092 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005093 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005094 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005095 pItem->val.expAndMantissa.nExponent,
5096 puValue,
5097 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005098 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005099 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005100 }
5101 break;
5102
5103 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005104 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005105 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
5106 pItem->val.expAndMantissa.nExponent,
5107 puValue,
5108 Exponentitate2);
5109 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005110 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005111 }
5112 break;
5113
5114 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005115 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005116 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005117 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005118 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005119 if(uErr != QCBOR_SUCCESS) {
5120 return uErr;
5121 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005122 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005123 pItem->val.expAndMantissa.nExponent,
5124 puValue,
5125 Exponentitate10);
5126 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005127 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005128 }
5129 break;
5130
5131 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005132 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005133 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5134 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005135 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005136 }
5137 break;
5138
5139 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005140 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005141 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005142 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005143 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005144 if(uErr != QCBOR_SUCCESS) {
5145 return uErr;
5146 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005147 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005148 pItem->val.expAndMantissa.nExponent,
5149 puValue,
5150 Exponentitate2);
5151 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005152 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005153 }
5154 break;
5155
5156 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005157 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005158 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5159 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005160 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005161 }
5162 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005163#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005164 default:
5165 return QCBOR_ERR_UNEXPECTED_TYPE;
5166 }
5167}
5168
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005169
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005170/*
5171 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005172 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005173void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005174{
5175 QCBORItem Item;
5176
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005177 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005178
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005179 if(pMe->uLastError == QCBOR_SUCCESS) {
5180 // The above conversion succeeded
5181 return;
5182 }
5183
5184 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5185 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005186 return;
5187 }
5188
Laurence Lundblade93d89472020-10-03 22:30:50 -07005189 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005190}
5191
Laurence Lundbladec4537442020-04-14 18:53:22 -07005192
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005193/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005194 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005195*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005196void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005197 int64_t nLabel,
5198 uint32_t uConvertTypes,
5199 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005200{
5201 QCBORItem Item;
5202
Laurence Lundblade93d89472020-10-03 22:30:50 -07005203 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5204 nLabel,
5205 uConvertTypes,
5206 puValue,
5207 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005208
5209 if(pMe->uLastError == QCBOR_SUCCESS) {
5210 // The above conversion succeeded
5211 return;
5212 }
5213
5214 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5215 // The above conversion failed in a way that code below can't correct
5216 return;
5217 }
5218
Laurence Lundblade93d89472020-10-03 22:30:50 -07005219 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005220}
5221
5222
5223/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005224 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005225*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005226void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005227 const char *szLabel,
5228 uint32_t uConvertTypes,
5229 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005230{
5231 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005232 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5233 szLabel,
5234 uConvertTypes,
5235 puValue,
5236 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005237
5238 if(pMe->uLastError == QCBOR_SUCCESS) {
5239 // The above conversion succeeded
5240 return;
5241 }
5242
5243 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5244 // The above conversion failed in a way that code below can't correct
5245 return;
5246 }
5247
Laurence Lundblade93d89472020-10-03 22:30:50 -07005248 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005249}
5250
5251
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005252
5253
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005254#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005255static QCBORError ConvertDouble(const QCBORItem *pItem,
5256 uint32_t uConvertTypes,
5257 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005258{
5259 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005260 case QCBOR_TYPE_FLOAT:
5261#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5262 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5263 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005264 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005265 *pdValue = (double)pItem->val.fnum;
5266 } else {
5267 return QCBOR_ERR_UNEXPECTED_TYPE;
5268 }
5269 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005270#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005271 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005272#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005273 break;
5274
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005275 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005276 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5277 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005278 *pdValue = pItem->val.dfnum;
5279 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005280 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005281 }
5282 }
5283 break;
5284
5285 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005286#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005287 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005288 // A simple cast seems to do the job with no worry of exceptions.
5289 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005290 *pdValue = (double)pItem->val.int64;
5291
5292 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005293 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005294 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005295#else
5296 return QCBOR_ERR_HW_FLOAT_DISABLED;
5297#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005298 break;
5299
5300 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005301#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005302 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005303 // A simple cast seems to do the job with no worry of exceptions.
5304 // There will be precision loss for some values.
5305 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005306 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005307 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005308 }
5309 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005310#else
5311 return QCBOR_ERR_HW_FLOAT_DISABLED;
5312#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005313
5314 default:
5315 return QCBOR_ERR_UNEXPECTED_TYPE;
5316 }
5317
5318 return QCBOR_SUCCESS;
5319}
5320
5321
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005322void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005323 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005324 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005325 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005326{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005327 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005328 return;
5329 }
5330
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005331 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005332
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005333 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005334 if(uError) {
5335 pMe->uLastError = (uint8_t)uError;
5336 return;
5337 }
5338
5339 if(pItem) {
5340 *pItem = Item;
5341 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005342
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005343 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005344}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005345
Laurence Lundbladec4537442020-04-14 18:53:22 -07005346
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005347void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5348 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005349 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005350 double *pdValue,
5351 QCBORItem *pItem)
5352{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005353 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005354 if(pMe->uLastError != QCBOR_SUCCESS) {
5355 return;
5356 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005357
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005358 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005359}
5360
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005361
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005362void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5363 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005364 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005365 double *pdValue,
5366 QCBORItem *pItem)
5367{
5368 if(pMe->uLastError != QCBOR_SUCCESS) {
5369 return;
5370 }
5371
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005372 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005373 if(pMe->uLastError != QCBOR_SUCCESS) {
5374 return;
5375 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005376
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005377 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005378}
5379
5380
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005381#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005382static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5383{
5384 double dResult;
5385
5386 dResult = 0.0;
5387 const uint8_t *pByte = BigNum.ptr;
5388 size_t uLen = BigNum.len;
5389 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005390 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005391 while(uLen--) {
5392 dResult = (dResult * 256.0) + (double)*pByte++;
5393 }
5394
5395 return dResult;
5396}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005397#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5398
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005399
Laurence Lundblade93d89472020-10-03 22:30:50 -07005400static QCBORError
5401DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005402{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005403#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005404 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005405 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5406 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5407 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005408 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005409
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005410#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005411 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005412 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005413 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005414 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5415 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5416 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005417 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005418 }
5419 break;
5420
5421 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005422 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005423 // Underflow gives 0, overflow gives infinity
5424 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5425 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005426 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005427 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005428 }
5429 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005430#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005431
5432 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005433 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005434 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5435 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005436 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005437 }
5438 break;
5439
5440 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005441 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005442 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005443 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005444 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005445 }
5446 break;
5447
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005448#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005449 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005450 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005451 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5452 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5453 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005454 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005455 }
5456 break;
5457
5458 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005459 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005460 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5461 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5462 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005463 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005464 }
5465 break;
5466
5467 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005468 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005469 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5470 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5471 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005472 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005473 }
5474 break;
5475
5476 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005477 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005478 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005479 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5480 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005481 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005482 }
5483 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005484#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005485
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005486 default:
5487 return QCBOR_ERR_UNEXPECTED_TYPE;
5488 }
5489
5490 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005491
5492#else
5493 (void)pItem;
5494 (void)uConvertTypes;
5495 (void)pdValue;
5496 return QCBOR_ERR_HW_FLOAT_DISABLED;
5497#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5498
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005499}
5500
5501
5502/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005503 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005504*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005505void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5506 uint32_t uConvertTypes,
5507 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005508{
5509
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005510 QCBORItem Item;
5511
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005512 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005513
5514 if(pMe->uLastError == QCBOR_SUCCESS) {
5515 // The above conversion succeeded
5516 return;
5517 }
5518
5519 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5520 // The above conversion failed in a way that code below can't correct
5521 return;
5522 }
5523
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005524 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005525}
5526
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005527
5528/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005529 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005530*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005531void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5532 int64_t nLabel,
5533 uint32_t uConvertTypes,
5534 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005535{
5536 QCBORItem Item;
5537
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005538 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005539
5540 if(pMe->uLastError == QCBOR_SUCCESS) {
5541 // The above conversion succeeded
5542 return;
5543 }
5544
5545 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5546 // The above conversion failed in a way that code below can't correct
5547 return;
5548 }
5549
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005550 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005551}
5552
5553
5554/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005555 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005556*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005557void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5558 const char *szLabel,
5559 uint32_t uConvertTypes,
5560 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005561{
5562 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005563 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005564
5565 if(pMe->uLastError == QCBOR_SUCCESS) {
5566 // The above conversion succeeded
5567 return;
5568 }
5569
5570 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5571 // The above conversion failed in a way that code below can't correct
5572 return;
5573 }
5574
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005575 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005576}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005577#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005578
5579
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005580
5581
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005582#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005583static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5584{
5585 while((uInt & 0xff00000000000000UL) == 0) {
5586 uInt = uInt << 8;
5587 };
5588
5589 UsefulOutBuf UOB;
5590
5591 UsefulOutBuf_Init(&UOB, Buffer);
5592
5593 while(uInt) {
5594 const uint64_t xx = uInt & 0xff00000000000000UL;
5595 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5596 uInt = uInt << 8;
5597 (void)xx;
5598 }
5599
5600 return UsefulOutBuf_OutUBuf(&UOB);
5601}
5602
5603
Laurence Lundblade37286c02022-09-03 10:05:02 -07005604/**
5605 * @brief Check and/or complete mantissa and exponent item.
5606 *
5607 * @param[in] pMe The decoder context
5608 * @param[in] TagSpec Expected type(s)
5609 * @param[in,out] pItem See below
5610 *
5611 * This is for decimal fractions and big floats, both of which are a
5612 * mantissa and exponent.
5613 *
5614 * The input item is either a fully decoded decimal faction or big
5615 * float, or a just the decoded first item of a decimal fraction or
5616 * big float.
5617 *
5618 * On output, the item is always a fully decoded decimal fraction or
5619 * big float.
5620 *
5621 * This errors out if the input type does not meet the TagSpec.
5622 */
5623// TODO: document and see tests for the bug that was fixed by this rewrite
5624static QCBORError
5625MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5626 const TagSpecification TagSpec,
5627 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005628{
5629 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005630
Laurence Lundblade37286c02022-09-03 10:05:02 -07005631 /* pItem could either be an auto-decoded mantissa and exponent or
5632 * the opening array of an undecoded mantissa and exponent. This
5633 * check will succeed on either, but doesn't say which it was.
5634 */
5635 uErr = CheckTagRequirement(TagSpec, pItem);
5636 if(uErr != QCBOR_SUCCESS) {
5637 goto Done;
5638 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005639
Laurence Lundblade37286c02022-09-03 10:05:02 -07005640 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
5641 /* The item is an array, which means is is an undecoded mantissa
5642 * and exponent. This call consumes the items in the array and
5643 * results in a decoded mantissa and exponent in pItem. This is
5644 * the case where there was no tag.
5645 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005646 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5647 if(uErr != QCBOR_SUCCESS) {
5648 goto Done;
5649 }
5650
Laurence Lundblade37286c02022-09-03 10:05:02 -07005651 /* The above decode didn't determine whether it is a decimal
5652 * fraction or big num. Which of these two depends on what the
5653 * caller wants it decoded as since there is no tag, so fish the
5654 * type out of the TagSpec. */
5655 pItem->uDataType = MantissaExponentDataType(TagSpec.uTaggedTypes[0], pItem);
5656
5657 /* No need to check the type again. All that we need to know was
5658 * that it decoded correctly as a mantissa and exponent. The
5659 * QCBOR type is set out by what was requested.
5660 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005661 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07005662
5663 /* If the item was not an array and the check passed, then
5664 * it is a fully decoded big float or decimal fraction and
5665 * matches what is requested.
5666 */
5667
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005668Done:
5669 return uErr;
5670}
5671
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005672
Laurence Lundblade37286c02022-09-03 10:05:02 -07005673/* Some notes from the work to disable tags.
5674 *
5675 * The API for big floats and decimal fractions seems good.
5676 * If there's any issue with it it's that the code size to
5677 * implement is a bit large because of the conversion
5678 * to/from int and bignum that is required. There is no API
5679 * that doesn't do the conversion so dead stripping will never
5680 * leave that code out.
5681 *
5682 * The implementation itself seems correct, but not as clean
5683 * and neat as it could be. It could probably be smaller too.
5684 *
5685 * The implementation has three main parts / functions
5686 * - The decoding of the array of two
5687 * - All the tag and type checking for the various API functions
5688 * - Conversion to/from bignum and int
5689 *
5690 * The type checking seems like it wastes the most code for
5691 * what it needs to do.
5692 *
5693 * The inlining for the conversion is probably making the
5694 * overall code base larger.
5695 *
5696 * The tests cases could be organized a lot better and be
5697 * more thorough.
5698 *
5699 * Seems also like there could be more common code in the
5700 * first tier part of the public API. Some functions only
5701 * vary by a TagSpec.
5702 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005703static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005704 TagSpecification TagSpec,
5705 QCBORItem *pItem,
5706 int64_t *pnMantissa,
5707 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005708{
5709 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005710
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005711 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005712 if(uErr != QCBOR_SUCCESS) {
5713 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005714 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005715
Laurence Lundblade9b334962020-08-27 10:55:53 -07005716 switch (pItem->uDataType) {
5717
5718 case QCBOR_TYPE_DECIMAL_FRACTION:
5719 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07005720 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005721 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005722 break;
5723
Laurence Lundblade37286c02022-09-03 10:05:02 -07005724#ifndef QCBOR_DISABLE_TAGS
5725 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005726 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5727 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5728 *pnExponent = pItem->val.expAndMantissa.nExponent;
5729 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5730 break;
5731
5732 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5733 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5734 *pnExponent = pItem->val.expAndMantissa.nExponent;
5735 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5736 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005737#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005738
5739 default:
5740 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5741 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005742
5743 Done:
5744 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005745}
5746
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005747
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005748static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005749 TagSpecification TagSpec,
5750 QCBORItem *pItem,
5751 UsefulBuf BufferForMantissa,
5752 UsefulBufC *pMantissa,
5753 bool *pbIsNegative,
5754 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005755{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005756 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005757
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005758 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005759 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005760 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005761 }
5762
5763 uint64_t uMantissa;
5764
5765 switch (pItem->uDataType) {
5766
5767 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005768 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005769 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5770 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5771 *pbIsNegative = false;
5772 } else {
5773 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5774 *pbIsNegative = true;
5775 }
5776 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5777 *pnExponent = pItem->val.expAndMantissa.nExponent;
5778 break;
5779
Laurence Lundblade37286c02022-09-03 10:05:02 -07005780#ifndef QCBOR_DISABLE_TAGS
5781 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005782 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005783 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005784 *pnExponent = pItem->val.expAndMantissa.nExponent;
5785 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5786 *pbIsNegative = false;
5787 break;
5788
5789 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005790 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005791 *pnExponent = pItem->val.expAndMantissa.nExponent;
5792 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5793 *pbIsNegative = true;
5794 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005795#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005796
5797 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005798 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005799 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005800
5801Done:
5802 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005803}
5804
5805
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005806/*
5807 Public function, see header qcbor/qcbor_decode.h file
5808*/
5809void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5810 uint8_t uTagRequirement,
5811 int64_t *pnMantissa,
5812 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005813{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005814 if(pMe->uLastError != QCBOR_SUCCESS) {
5815 return;
5816 }
5817
5818 QCBORItem Item;
5819 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5820 if(uError) {
5821 pMe->uLastError = (uint8_t)uError;
5822 return;
5823 }
5824
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005825 const TagSpecification TagSpec =
5826 {
5827 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005828 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5829 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5830 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005831 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005832
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005833 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005834}
5835
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005836
5837/*
5838 Public function, see header qcbor/qcbor_decode.h file
5839*/
5840void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005841 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005842 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005843 int64_t *pnMantissa,
5844 int64_t *pnExponent)
5845{
5846 if(pMe->uLastError != QCBOR_SUCCESS) {
5847 return;
5848 }
5849
5850 QCBORItem Item;
5851 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5852
5853 const TagSpecification TagSpec =
5854 {
5855 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005856 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5857 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5858 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005859 };
5860
5861 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5862}
5863
5864
5865/*
5866 Public function, see header qcbor/qcbor_decode.h file
5867*/
5868void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005869 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005870 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005871 int64_t *pnMantissa,
5872 int64_t *pnExponent)
5873{
5874 if(pMe->uLastError != QCBOR_SUCCESS) {
5875 return;
5876 }
5877
5878 QCBORItem Item;
5879 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5880
5881 const TagSpecification TagSpec =
5882 {
5883 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005884 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5885 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5886 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005887 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005888
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005889 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5890}
5891
5892
5893/*
5894 Public function, see header qcbor/qcbor_decode.h file
5895*/
5896void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5897 uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07005898 UsefulBuf MantissaBuffer,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005899 UsefulBufC *pMantissa,
5900 bool *pbMantissaIsNegative,
5901 int64_t *pnExponent)
5902{
5903 if(pMe->uLastError != QCBOR_SUCCESS) {
5904 return;
5905 }
5906
5907 QCBORItem Item;
5908 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5909 if(uError) {
5910 pMe->uLastError = (uint8_t)uError;
5911 return;
5912 }
5913
5914 const TagSpecification TagSpec =
5915 {
5916 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005917 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5918 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5919 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005920 };
5921
Laurence Lundblade93d89472020-10-03 22:30:50 -07005922 ProcessMantissaAndExponentBig(pMe,
5923 TagSpec,
5924 &Item,
5925 MantissaBuffer,
5926 pMantissa,
5927 pbMantissaIsNegative,
5928 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005929}
5930
5931
5932/*
5933 Public function, see header qcbor/qcbor_decode.h file
5934*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005935void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005936 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005937 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005938 UsefulBuf BufferForMantissa,
5939 UsefulBufC *pMantissa,
5940 bool *pbIsNegative,
5941 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005942{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005943 if(pMe->uLastError != QCBOR_SUCCESS) {
5944 return;
5945 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005946
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005947 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005948 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005949 if(pMe->uLastError != QCBOR_SUCCESS) {
5950 return;
5951 }
5952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005953 const TagSpecification TagSpec =
5954 {
5955 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005956 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5957 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5958 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005959 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005960
Laurence Lundblade93d89472020-10-03 22:30:50 -07005961 ProcessMantissaAndExponentBig(pMe,
5962 TagSpec,
5963 &Item,
5964 BufferForMantissa,
5965 pMantissa,
5966 pbIsNegative,
5967 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005968}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005969
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005970
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005971/*
5972 Public function, see header qcbor/qcbor_decode.h file
5973*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005974void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005975 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005976 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005977 UsefulBuf BufferForMantissa,
5978 UsefulBufC *pMantissa,
5979 bool *pbIsNegative,
5980 int64_t *pnExponent)
5981{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005982 if(pMe->uLastError != QCBOR_SUCCESS) {
5983 return;
5984 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005985
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005986 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005987 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5988 if(pMe->uLastError != QCBOR_SUCCESS) {
5989 return;
5990 }
5991
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005992 const TagSpecification TagSpec =
5993 {
5994 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005995 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5996 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5997 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005998 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005999
6000 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
6001}
6002
6003
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006004/*
6005 Public function, see header qcbor/qcbor_decode.h file
6006*/
6007void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6008 uint8_t uTagRequirement,
6009 int64_t *pnMantissa,
6010 int64_t *pnExponent)
6011{
6012 if(pMe->uLastError != QCBOR_SUCCESS) {
6013 return;
6014 }
6015
6016 QCBORItem Item;
6017 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6018 if(uError) {
6019 pMe->uLastError = (uint8_t)uError;
6020 return;
6021 }
6022 const TagSpecification TagSpec =
6023 {
6024 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006025 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6026 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6027 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006028 };
6029
6030 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6031}
6032
6033
6034/*
6035 Public function, see header qcbor/qcbor_decode.h file
6036*/
6037void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006038 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006039 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006040 int64_t *pnMantissa,
6041 int64_t *pnExponent)
6042{
6043 if(pMe->uLastError != QCBOR_SUCCESS) {
6044 return;
6045 }
6046
6047 QCBORItem Item;
6048 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6049 if(pMe->uLastError != QCBOR_SUCCESS) {
6050 return;
6051 }
6052
6053 const TagSpecification TagSpec =
6054 {
6055 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006056 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6057 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6058 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006059 };
6060
6061 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6062}
6063
6064
6065/*
6066 Public function, see header qcbor/qcbor_decode.h file
6067*/
6068void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006069 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006070 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006071 int64_t *pnMantissa,
6072 int64_t *pnExponent)
6073{
6074 if(pMe->uLastError != QCBOR_SUCCESS) {
6075 return;
6076 }
6077
6078 QCBORItem Item;
6079 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6080 if(pMe->uLastError != QCBOR_SUCCESS) {
6081 return;
6082 }
6083
6084 const TagSpecification TagSpec =
6085 {
6086 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006087 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6088 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6089 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006090 };
6091
6092 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6093}
6094
6095
6096/*
6097 Public function, see header qcbor/qcbor_decode.h file
6098*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006099void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6100 uint8_t uTagRequirement,
6101 UsefulBuf MantissaBuffer,
6102 UsefulBufC *pMantissa,
6103 bool *pbMantissaIsNegative,
6104 int64_t *pnExponent)
6105{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006106 if(pMe->uLastError != QCBOR_SUCCESS) {
6107 return;
6108 }
6109
6110 QCBORItem Item;
6111 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6112 if(uError) {
6113 pMe->uLastError = (uint8_t)uError;
6114 return;
6115 }
6116
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006117 const TagSpecification TagSpec =
6118 {
6119 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006120 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6121 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6122 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006123 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006124
6125 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006126}
6127
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006128
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006129/*
6130 Public function, see header qcbor/qcbor_decode.h file
6131*/
6132void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006133 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006134 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006135 UsefulBuf BufferForMantissa,
6136 UsefulBufC *pMantissa,
6137 bool *pbIsNegative,
6138 int64_t *pnExponent)
6139{
6140 if(pMe->uLastError != QCBOR_SUCCESS) {
6141 return;
6142 }
6143
6144 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006145 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6146 if(pMe->uLastError != QCBOR_SUCCESS) {
6147 return;
6148 }
6149
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006150 const TagSpecification TagSpec =
6151 {
6152 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006153 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6154 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6155 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006156 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006157
Laurence Lundblade93d89472020-10-03 22:30:50 -07006158 ProcessMantissaAndExponentBig(pMe,
6159 TagSpec,
6160 &Item,
6161 BufferForMantissa,
6162 pMantissa,
6163 pbIsNegative,
6164 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006165}
6166
6167
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006168/*
6169 Public function, see header qcbor/qcbor_decode.h file
6170*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006171void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006172 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006173 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006174 UsefulBuf BufferForMantissa,
6175 UsefulBufC *pMantissa,
6176 bool *pbIsNegative,
6177 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006178{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006179 if(pMe->uLastError != QCBOR_SUCCESS) {
6180 return;
6181 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006182
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006183 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006184 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6185 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006186 return;
6187 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006188
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006189 const TagSpecification TagSpec =
6190 {
6191 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006192 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6193 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6194 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006195 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006196
Laurence Lundblade93d89472020-10-03 22:30:50 -07006197 ProcessMantissaAndExponentBig(pMe,
6198 TagSpec,
6199 &Item,
6200 BufferForMantissa,
6201 pMantissa,
6202 pbIsNegative,
6203 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006204}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006205
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006206#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */