blob: 6353fee27d501d6e694cc47bb8d76b299f77d995 [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{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300504 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
505 * This is the one place where the const needs to be cast away so const can
506 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800507 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300508 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800509}
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511// StringAllocator_Reallocate called with pMem NULL is
512// equal to StringAllocator_Allocate()
513static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800514StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800515 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800517{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800518 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300519 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520}
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800523StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800529StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800531 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800532 if(pMe->pfAllocator) {
533 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
534 }
535}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800536#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537
538
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800539
540
Laurence Lundbladeee851742020-01-08 08:37:05 -0800541/*===========================================================================
542 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700543
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800544 See qcbor/qcbor_decode.h for definition of the object
545 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800548 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800550void QCBORDecode_Init(QCBORDecodeContext *pMe,
551 UsefulBufC EncodedCBOR,
552 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800554 memset(pMe, 0, sizeof(QCBORDecodeContext));
555 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
556 /* Don't bother with error check on decode mode. If a bad value is
557 * passed it will just act as if the default normal mode of 0 was set.
558 */
559 pMe->uDecodeMode = (uint8_t)nDecodeMode;
560 DecodeNesting_Init(&(pMe->nesting));
561
562 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
563 * GetNext_TaggedItem() and MapTagNumber(). */
564 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700565}
566
567
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800568#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
569
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800571 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700572 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
574 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800575 void *pAllocateContext,
576 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
579 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
580 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800582#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700583
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800584
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800585
586
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800588 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800590void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700592{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800593 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700594 (void)pMe;
595 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700596}
597
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800599
600
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700601/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800602 * Decoding items is done in six layers, one calling the next one
603 * down. If a layer has no work to do for a particular item, it
604 * returns quickly.
605 *
606 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
607 * data items, turning them into the local C representation. For the
608 * most simple it is just associating a QCBOR_TYPE with the data. For
609 * the complex ones that an aggregate of data items, there is some
610 * further decoding and some limited recursion.
611 *
612 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
613 * ends of maps and arrays. It tracks descending into and ascending
614 * out of maps/arrays. It processes breaks that terminate
615 * indefinite-length maps and arrays.
616 *
617 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
618 * items, the label and the data, that make up a map entry. It only
619 * does work on maps. It combines the label and data items into one
620 * labeled item.
621 *
622 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
623 * numbers. It turns the tag numbers into bit flags associated with
624 * the data item. No actual decoding of the contents of the tag is
625 * performed here.
626 *
627 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
628 * that make up an indefinite-length string into one string item. It
629 * uses the string allocator to create contiguous space for the
630 * item. It processes all breaks that are part of indefinite-length
631 * strings.
632 *
633 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
634 * CBOR. Each atomic data item has a "major type", an integer
635 * "argument" and optionally some content. For text and byte strings,
636 * the content is the bytes that make up the string. These are the
637 * smallest data items that are considered to be well-formed. The
638 * content may also be other data items in the case of aggregate
639 * types. They are not handled in this layer.
640 *
641 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
642 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700643 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800644
645
646/*
647 * Note about use of int and unsigned variables.
648 *
649 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
650 * used carefully here, and in particular why it isn't used in the
651 * public interface. Also see
652 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
653 *
654 * Int is used for values that need less than 16-bits and would be
655 * subject to integer promotion and result in complaining from static
656 * analyzers.
657 */
658
659
660/**
661 * @brief Decode the CBOR head, the type and argument.
662 *
663 * @param[in] pUInBuf The input buffer to read from.
664 * @param[out] pnMajorType The decoded major type.
665 * @param[out] puArgument The decoded argument.
666 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
667 *
668 * @retval QCBOR_ERR_UNSUPPORTED
669 * @retval QCBOR_ERR_HIT_END
670 *
671 * This decodes the CBOR "head" that every CBOR data item has. See
672 * longer explaination of the head in documentation for
673 * QCBOREncode_EncodeHead().
674 *
675 * This does the network->host byte order conversion. The conversion
676 * here also results in the conversion for floats in addition to that
677 * for lengths, tags and integer values.
678 *
679 * The int type is preferred to uint8_t for some variables as this
680 * avoids integer promotions, can reduce code size and makes static
681 * analyzers happier.
682 */
683static inline QCBORError
684DecodeHead(UsefulInputBuf *pUInBuf,
685 int *pnMajorType,
686 uint64_t *puArgument,
687 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800689 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800690
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800691 /* Get the initial byte that every CBOR data item has and break it
692 * down. */
693 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 const int nTmpMajorType = nInitialByte >> 5;
695 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800697 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800698 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800699
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800700 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800701 /* Need to get 1,2,4 or 8 additional argument bytes. Map
702 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
703 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800704 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800705
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800706 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800707 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800708 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800709 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800710 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
711 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800712 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800713 /* The reserved and thus-far unused additional info values */
714 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800715 goto Done;
716 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800717 /* Less than 24, additional info is argument or 31, an
718 * indefinite-length. No more bytes to get.
719 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800720 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800724 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 goto Done;
726 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800727
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800728 /* All successful if arrived here. */
729 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800730 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800731 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800732 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800733
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800735 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736}
737
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800739/**
740 * @brief Decode integer types, major types 0 and 1.
741 *
742 * @param[in] nMajorType The CBOR major type (0 or 1).
743 * @param[in] uArgument The argument from the head.
744 * @param[out] pDecodedItem The filled in decoded item.
745 *
746 * @retval QCBOR_ERR_INT_OVERFLOW
747 *
748 * Must only be called when major type is 0 or 1.
749 *
750 * CBOR doesn't explicitly specify two's compliment for integers but
751 * all CPUs use it these days and the test vectors in the RFC are
752 * so. All integers in the CBOR structure are positive and the major
753 * type indicates positive or negative. CBOR can express positive
754 * integers up to 2^x - 1 where x is the number of bits and negative
755 * integers down to 2^x. Note that negative numbers can be one more
756 * away from zero than positive. Stdint, as far as I can tell, uses
757 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700758 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700759static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800760DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700761{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800762 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700764 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800765 if (uArgument <= INT64_MAX) {
766 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800770 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800773
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800775 if(uArgument <= INT64_MAX) {
776 /* CBOR's representation of negative numbers lines up with
777 * the two-compliment representation. A negative integer has
778 * one more in range than a positive integer. INT64_MIN is
779 * equal to (-INT64_MAX) - 1.
780 */
781 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800783
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700784 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800785 /* C can't represent a negative integer in this range so it
786 * is an error.
787 */
788 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700789 }
790 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800792 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793}
794
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800795
796/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
798#error QCBOR_TYPE_FALSE macro value wrong
799#endif
800
801#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
802#error QCBOR_TYPE_TRUE macro value wrong
803#endif
804
805#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
806#error QCBOR_TYPE_NULL macro value wrong
807#endif
808
809#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
810#error QCBOR_TYPE_UNDEF macro value wrong
811#endif
812
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700813#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
814#error QCBOR_TYPE_BREAK macro value wrong
815#endif
816
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
818#error QCBOR_TYPE_DOUBLE macro value wrong
819#endif
820
821#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
822#error QCBOR_TYPE_FLOAT macro value wrong
823#endif
824
Laurence Lundblade9b334962020-08-27 10:55:53 -0700825
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800826/**
827 * @brief Decode major type 7 -- true, false, floating-point, break...
828 *
829 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
830 * @param[in] uArgument The argument from the head.
831 * @param[out] pDecodedItem The filled in decoded item.
832 *
833 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200834 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800837
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800838static inline QCBORError
839DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
840{
841 QCBORError uReturn = QCBOR_SUCCESS;
842
843 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
844 * checks above make sure uAdditionalInfo values line up with
845 * uDataType values. DecodeHead() never returns an AdditionalInfo
846 * > 0x1f so cast is safe.
847 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800849
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800851 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
852 * are caught before this is called.
853 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800855 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700856#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800857 /* Half-precision is returned as a double. The cast to
858 * uint16_t is safe because the encoded value was 16 bits. It
859 * was widened to 64 bits to be passed in here.
860 */
861 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700862 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200864 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700865 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800866 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200867#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800868 /* Single precision is normally returned as a double since
869 * double is widely supported, there is no loss of precision,
870 * it makes it easy for the caller in most cases and it can
871 * be converted back to single with no loss of precision
872 *
873 * The cast to uint32_t is safe because the encoded value was
874 * 32 bits. It was widened to 64 bits to be passed in here.
875 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700878#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800879 /* In the normal case, use HW to convert float to
880 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700881 pDecodedItem->val.dfnum = (double)f;
882 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800883#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800884 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885 pDecodedItem->val.fnum = f;
886 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
887
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800888 /* IEEE754_FloatToDouble() could be used here to return as
889 * a double, but it adds object code and most likely
890 * anyone disabling FLOAT HW use doesn't care about floats
891 * and wants to save object code.
892 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800893#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200895#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
896 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700897 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700898
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800899 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200900#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800901 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700902 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200903#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
904 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700905 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800907 case CBOR_SIMPLEV_FALSE: /* 20 */
908 case CBOR_SIMPLEV_TRUE: /* 21 */
909 case CBOR_SIMPLEV_NULL: /* 22 */
910 case CBOR_SIMPLEV_UNDEF: /* 23 */
911 case CBOR_SIMPLE_BREAK: /* 31 */
912 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800914 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
915 if(uArgument <= CBOR_SIMPLE_BREAK) {
916 /* This takes out f8 00 ... f8 1f which should be encoded
917 * as e0 … f7
918 */
919 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 goto Done;
921 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800922 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800924 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926 /* DecodeHead() will make uArgument equal to
927 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
928 * safe because the 2, 4 and 8 byte lengths of uNumber are in
929 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800930 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800931 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932 break;
933 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800936 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700937}
938
939
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800940/**
941 * @brief Decode text and byte strings
942 *
943 * @param[in] pAllocator The string allocator or NULL.
944 * @param[in] uStrLen The length of the string.
945 * @param[in] pUInBuf The surce from which to read the string's bytes.
946 * @param[out] pDecodedItem The filled in decoded item.
947 *
948 * @retval QCBOR_ERR_HIT_END
949 * @retval QCBOR_ERR_STRING_ALLOCATE
950 * @retval QCBOR_ERR_STRING_TOO_LONG
951 *
952 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
953 * pDecodedItem. If @c pAllocator is not NULL then memory for the
954 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700955 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800956static inline QCBORError
957DecodeBytes(const QCBORInternalAllocator *pAllocator,
958 uint64_t uStrLen,
959 UsefulInputBuf *pUInBuf,
960 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800962 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800963
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800964 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
965 * CPUs. This check makes the casts to size_t below safe.
966 *
967 * The max is 4 bytes less than the largest sizeof() so this can be
968 * tested by putting a SIZE_MAX length in the CBOR test input (no
969 * one will care the limit on strings is 4 bytes shorter).
970 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800971 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 goto Done;
974 }
975
976 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530977 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800978 /* Failed to get the bytes for this string item */
979 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530980 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530982
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800983#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800984 /* Note that this is not where allocation to coalesce
985 * indefinite-length strings is done. This is for when the caller
986 * has requested all strings be allocated. Disabling indefinite
987 * length strings also disables this allocate-all option.
988 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800989 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800990 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800991 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530994 goto Done;
995 }
996 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800997 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800998 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530999 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001000#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1001 (void)pAllocator;
1002#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1003
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001004 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001005 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301007Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001008 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009}
1010
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001011
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001012/**
1013 * @brief Map the CBOR major types for strings to the QCBOR types.
1014 *
1015 * @param[in] nCBORMajorType The CBOR major type to convert.
1016 * @retturns QCBOR type number.
1017 *
1018 * This only works for the two string types.
1019 */
1020static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021{
1022 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1023 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1024 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001026 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1027 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1028 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001030 return (uint8_t)(nCBORMajorType + 4);
1031}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032
1033
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001034/**
1035 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1036 *
1037 * @param[in] nCBORMajorType The CBOR major type to convert.
1038 * @retturns QCBOR type number.
1039 *
1040 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001042static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001043{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001044 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1045 #error QCBOR_TYPE_ARRAY value not lined up with major type
1046 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001047
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001048 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1049 #error QCBOR_TYPE_MAP value not lined up with major type
1050 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001051
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001052 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053}
1054
1055
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001056/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001057 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001058 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001059 * @param[in] pUInBuf Input buffer to read data item from.
1060 * @param[out] pDecodedItem The filled-in decoded item.
1061 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001062 *
1063 * @retval QCBOR_ERR_UNSUPPORTED
1064 * @retval QCBOR_ERR_HIT_END
1065 * @retval QCBOR_ERR_INT_OVERFLOW
1066 * @retval QCBOR_ERR_STRING_ALLOCATE
1067 * @retval QCBOR_ERR_STRING_TOO_LONG
1068 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001069 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001070 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001071 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1072 *
1073 * This decodes the most primitive / atomic data item. It does
1074 * no combing of data items.
1075 */
1076static QCBORError
1077DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1078 QCBORItem *pDecodedItem,
1079 const QCBORInternalAllocator *pAllocator)
1080{
1081 QCBORError uReturn;
1082
1083 /* Get the major type and the argument. The argument could be
1084 * length of more bytes or the value depending on the major
1085 * type. nAdditionalInfo is an encoding of the length of the
1086 * uNumber and is needed to decode floats and doubles.
1087 */
1088 int nMajorType = 0;
1089 uint64_t uArgument = 0;
1090 int nAdditionalInfo = 0;
1091
1092 memset(pDecodedItem, 0, sizeof(QCBORItem));
1093
1094 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1095 if(uReturn) {
1096 goto Done;
1097 }
1098
1099 /* At this point the major type and the argument are valid. We've
1100 * got the type and the argument that starts every CBOR data item.
1101 */
1102 switch (nMajorType) {
1103 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1104 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1105 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1106 uReturn = QCBOR_ERR_BAD_INT;
1107 } else {
1108 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1109 }
1110 break;
1111
1112 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1113 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1114 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1115 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1116 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1117 } else {
1118 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1119 }
1120 break;
1121
1122 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1123 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1124 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1125 /* Indefinite-length string. */
1126#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1127 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1128#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1129 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1130 break;
1131#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1132 } else {
1133 /* Definite-length string. */
1134 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1135 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1136 goto Done;
1137 }
1138 /* cast OK because of check above */
1139 pDecodedItem->val.uCount = (uint16_t)uArgument;
1140 }
1141 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1142 break;
1143
1144 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001145#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001146 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1147 uReturn = QCBOR_ERR_BAD_INT;
1148 } else {
1149 pDecodedItem->val.uTagV = uArgument;
1150 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1151 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001152#else /* QCBOR_DISABLE_TAGS */
1153 uReturn = QCBOR_ERR_TAGS_DISABLED;
1154#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001155 break;
1156
1157 case CBOR_MAJOR_TYPE_SIMPLE:
1158 /* Major type 7: float, double, true, false, null... */
1159 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1160 break;
1161
1162 default:
1163 /* Never happens because DecodeHead() should never return > 7 */
1164 uReturn = QCBOR_ERR_UNSUPPORTED;
1165 break;
1166 }
1167
1168Done:
1169 return uReturn;
1170}
1171
1172
1173/**
1174 * @brief Process indefinite-length strings (decode layer 5).
1175 *
1176 * @param[in] pMe Decoder context
1177 * @param[out] pDecodedItem The decoded item that work is done on.
1178 *
1179 * @retval QCBOR_ERR_UNSUPPORTED
1180 * @retval QCBOR_ERR_HIT_END
1181 * @retval QCBOR_ERR_INT_OVERFLOW
1182 * @retval QCBOR_ERR_STRING_ALLOCATE
1183 * @retval QCBOR_ERR_STRING_TOO_LONG
1184 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001185 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001186 * @retval QCBOR_ERR_BAD_TYPE_7
1187 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001188 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1189 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001190 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001191 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001192 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001194 * If it is, this loops getting the subsequent chunk data items that
1195 * make up the string. The string allocator is used to make a
1196 * contiguous buffer for the chunks. When this completes @c
1197 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 *
1199 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001200 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001201static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001202QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001203{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204 /* Aproximate stack usage
1205 * 64-bit 32-bit
1206 * local vars 32 16
1207 * 2 UsefulBufs 32 16
1208 * QCBORItem 56 52
1209 * TOTAL 120 74
1210 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001211
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001212 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001213 * coalescing the chunks of an indefinite-length string, 2)
1214 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001215 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001216 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217 * strings cannot be processed at all without a string allocator.
1218 *
1219 * The second used is in DecodeBytes() which is called by
1220 * GetNext_Item() below. This second use unneccessary for most use
1221 * and only happens when requested in the call to
1222 * QCBORDecode_SetMemPool(). If the second use not requested then
1223 * NULL is passed for the string allocator to GetNext_Item().
1224 *
1225 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1226 * allocator altogether and thus both of these uses. It reduced the
1227 * decoder object code by about 400 bytes.
1228 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001229 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001231#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001232 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001233
1234 if(pMe->StringAllocator.pfAllocator) {
1235 pAllocator = &(pMe->StringAllocator);
1236 if(pMe->bStringAllocateAll) {
1237 pAllocatorForGetNext = pAllocator;
1238 }
1239 }
1240#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1241
1242 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001243 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001244 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001245 goto Done;
1246 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001248 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001249 const uint8_t uStringType = pDecodedItem->uDataType;
1250 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001251 goto Done;
1252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001253
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001254 /* Is this a string with an indefinite length? */
1255 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1256 goto Done;
1257 }
1258
1259#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001260 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001261 if(pAllocator == NULL) {
1262 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1263 goto Done;
1264 }
1265
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001266 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001267 UsefulBufC FullString = NULLUsefulBufC;
1268
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001269 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001270 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001271 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001272 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001273 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001274 * be allocated. They are always copied in the the contiguous
1275 * buffer allocated here.
1276 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001277 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001278 if(uReturn) {
1279 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001280 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001281
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001282 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001283 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001284 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301286 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001287 break;
1288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001289
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001290 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001291 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001293 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001294 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001295 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001296 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1297 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001298 break;
1299 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001300
David Navarro9123e5b2022-03-28 16:04:03 +02001301 if (StringChunkItem.val.string.len > 0) {
1302 /* The first time throurgh FullString.ptr is NULL and this is
1303 * equivalent to StringAllocator_Allocate(). Subsequently it is
1304 * not NULL and a reallocation happens.
1305 */
1306 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1307 FullString.ptr,
1308 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001309
David Navarro9123e5b2022-03-28 16:04:03 +02001310 if(UsefulBuf_IsNULL(NewMem)) {
1311 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1312 break;
1313 }
1314
1315 /* Copy new string chunk to the end of accumulated string */
1316 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001317 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001318 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001319
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001320 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1321 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001322 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001323 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001324#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1325 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1326#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001328Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001329 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001330}
1331
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001332
Laurence Lundblade37286c02022-09-03 10:05:02 -07001333#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001334/**
1335 * @brief This converts a tag number to a shorter mapped value for storage.
1336 *
1337 * @param[in] pMe The decode context.
1338 * @param[in] uUnMappedTag The tag number to map
1339 * @param[out] puMappedTagNumer The stored tag number.
1340 *
1341 * @return error code.
1342 *
1343 * The main point of mapping tag numbers is make QCBORItem
1344 * smaller. With this mapping storage of 4 tags takes up 8
1345 * bytes. Without, it would take up 32 bytes.
1346 *
1347 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1348 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1349 *
1350 * See also UnMapTagNumber() and @ref QCBORItem.
1351 */
1352static inline QCBORError
1353MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1354{
1355 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1356 unsigned uTagMapIndex;
1357 /* Is there room in the tag map, or is it in it already? */
1358 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1359 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1360 break;
1361 }
1362 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1363 break;
1364 }
1365 }
1366 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1367 return QCBOR_ERR_TOO_MANY_TAGS;
1368 }
1369
1370 /* Covers the cases where tag is new and were it is already in the map */
1371 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1372 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1373
1374 } else {
1375 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1376 }
1377
1378 return QCBOR_SUCCESS;
1379}
1380
1381
1382/**
1383 * @brief This converts a mapped tag number to the actual tag number.
1384 *
1385 * @param[in] pMe The decode context.
1386 * @param[in] uMappedTagNumber The stored tag number.
1387 *
1388 * @return The actual tag number is returned or
1389 * @ref CBOR_TAG_INVALID64 on error.
1390 *
1391 * This is the reverse of MapTagNumber()
1392 */
1393static uint64_t
1394UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1395{
1396 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1397 return uMappedTagNumber;
1398 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001399 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001400 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001401 /* This won't be negative because of code below in
1402 * MapTagNumber()
1403 */
1404 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1405 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001406 }
1407}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001408#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001409
Laurence Lundblade9b334962020-08-27 10:55:53 -07001410
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001411/**
1412 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1413 *
1414 * @param[in] pMe Decoder context
1415 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001416
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001417 * @retval QCBOR_ERR_UNSUPPORTED
1418 * @retval QCBOR_ERR_HIT_END
1419 * @retval QCBOR_ERR_INT_OVERFLOW
1420 * @retval QCBOR_ERR_STRING_ALLOCATE
1421 * @retval QCBOR_ERR_STRING_TOO_LONG
1422 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001423 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001424 * @retval QCBOR_ERR_BAD_TYPE_7
1425 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1426 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1427 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1428 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1429 * @retval QCBOR_ERR_TOO_MANY_TAGS
1430 *
1431 * This loops getting atomic data items until one is not a tag
1432 * number. Usually this is largely pass-through because most
1433 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001434 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001435static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001436QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001437{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001438#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001439 /* Accummulate the tags from multiple items here and then copy them
1440 * into the last item, the non-tag item.
1441 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001442 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1443
1444 /* Initialize to CBOR_TAG_INVALID16 */
1445 #if CBOR_TAG_INVALID16 != 0xffff
1446 /* Be sure the memset does the right thing. */
1447 #err CBOR_TAG_INVALID16 tag not defined as expected
1448 #endif
1449 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001450
Laurence Lundblade9b334962020-08-27 10:55:53 -07001451 QCBORError uReturn = QCBOR_SUCCESS;
1452
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001453 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001454 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001456 if(uErr != QCBOR_SUCCESS) {
1457 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001458 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001459 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001460
Laurence Lundblade9b334962020-08-27 10:55:53 -07001461 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001462 /* Successful exit from loop; maybe got some tags, maybe not */
1463 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001464 break;
1465 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001466
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001467 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1468 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001469 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001470 /* Continue on to get all tags wrapping this item even though
1471 * it is erroring out in the end. This allows decoding to
1472 * continue. This is a resource limit error, not a problem
1473 * with being well-formed CBOR.
1474 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001475 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001476 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001477 /* Slide tags over one in the array to make room at index 0.
1478 * Must use memmove because the move source and destination
1479 * overlap.
1480 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001481 memmove(&auItemsTags[1],
1482 auItemsTags,
1483 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001484
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001485 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001486 uint16_t uMappedTagNumber = 0;
1487 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001488 /* Continue even on error so as to consume all tags wrapping
1489 * this data item so decoding can go on. If MapTagNumber()
1490 * errors once it will continue to error.
1491 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001492 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001493 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001495Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001496 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001497
Laurence Lundblade37286c02022-09-03 10:05:02 -07001498#else /* QCBOR_DISABLE_TAGS */
1499
1500 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1501
1502#endif /* QCBOR_DISABLE_TAGS */
1503}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001504
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001505/**
1506 * @brief Combine a map entry label and value into one item (decode layer 3).
1507 *
1508 * @param[in] pMe Decoder context
1509 * @param[out] pDecodedItem The decoded item that work is done on.
1510 *
1511 * @retval QCBOR_ERR_UNSUPPORTED
1512 * @retval QCBOR_ERR_HIT_END
1513 * @retval QCBOR_ERR_INT_OVERFLOW
1514 * @retval QCBOR_ERR_STRING_ALLOCATE
1515 * @retval QCBOR_ERR_STRING_TOO_LONG
1516 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001517 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001518 * @retval QCBOR_ERR_BAD_TYPE_7
1519 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1520 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1521 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1522 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1523 * @retval QCBOR_ERR_TOO_MANY_TAGS
1524 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1525 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1526 *
1527 * If a the current nesting level is a map, then this
1528 * combines pairs of items into one data item with a label
1529 * and value.
1530 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001531 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001532 * not a map.
1533 *
1534 * This also implements maps-as-array mode where a map
1535 * is treated like an array to allow caller to do their
1536 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001537 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001538static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001539QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001540{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001541 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1542 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001543 goto Done;
1544 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001546 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1547 /* Break can't be a map entry */
1548 goto Done;
1549 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001550
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001551 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1552 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001553
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001554 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1555 /* Save label in pDecodedItem and get the next which will
1556 * be the real data item.
1557 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001558 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001559 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1560 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001561 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001562 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001563
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301564 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001565
1566 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001567 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001568 pDecodedItem->label.string = LabelItem.val.string;
1569 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001570 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1571 /* It's not a string and we only want strings */
1572 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001573 goto Done;
1574 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1575 pDecodedItem->label.int64 = LabelItem.val.int64;
1576 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1577 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1578 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1579 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1580 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1581 pDecodedItem->label.string = LabelItem.val.string;
1582 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1583 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1584 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001585 /* label is not an int or a string. It is an arrray
1586 * or a float or such and this implementation doesn't handle that.
1587 * Also, tags on labels are ignored.
1588 */
1589 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001590 goto Done;
1591 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001592 }
1593 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594 /* Decoding of maps as arrays to let the caller decide what to do
1595 * about labels, particularly lables that are not integers or
1596 * strings.
1597 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001598 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001599 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001600 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001601 goto Done;
1602 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001603 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001604 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1605 * Cast is needed because of integer promotion.
1606 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001607 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001608 }
1609 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001610
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001611Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001612 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001613}
1614
1615
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001616#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001617/**
1618 * @brief Peek and see if next data item is a break;
1619 *
1620 * @param[in] pUIB UsefulInputBuf to read from.
1621 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1622 *
1623 * @return Any decoding error.
1624 *
1625 * See if next item is a CBOR break. If it is, it is consumed,
1626 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001627*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001628static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001629NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1630{
1631 *pbNextIsBreak = false;
1632 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001633 QCBORItem Peek;
1634 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001635 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001636 if(uReturn != QCBOR_SUCCESS) {
1637 return uReturn;
1638 }
1639 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001640 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001641 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001642 } else {
1643 *pbNextIsBreak = true;
1644 }
1645 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001646
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001647 return QCBOR_SUCCESS;
1648}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001649#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001650
1651
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001652/**
1653 * @brief Ascend up nesting levels if all items in them have been consumed.
1654 *
1655 * @param[in] pMe The decode context.
1656 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1657 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001658 * An item was just consumed, now figure out if it was the
1659 * end of an array/map map that can be closed out. That
1660 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001661*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001662static QCBORError
1663QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001664{
1665 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001666
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001667 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001668 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1669
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001670 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1671 /* Nesting level is bstr-wrapped CBOR */
1672
1673 /* Ascent for bstr-wrapped CBOR is always by explicit call
1674 * so no further ascending can happen.
1675 */
1676 break;
1677
1678 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1679 /* Level is a definite-length array/map */
1680
1681 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001682 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1683 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001684 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001685 break;
1686 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001687 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688 * is time to ascend one level. This happens below.
1689 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001690
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001691#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001692 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001693 /* Level is an indefinite-length array/map. */
1694
1695 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001696 bool bIsBreak = false;
1697 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1698 if(uReturn != QCBOR_SUCCESS) {
1699 goto Done;
1700 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001701
1702 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001703 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001704 break;
1705 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001707 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001708 * it is time to ascend one level.
1709 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001710
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001711#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001712 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001713
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001714
1715 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001716
Laurence Lundblade93d89472020-10-03 22:30:50 -07001717 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001718 * QCBORDecode_ExitBoundedMode().
1719 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001720 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001721 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001722 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001723 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001724 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001725 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001726
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001727 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001728 break;
1729 }
1730
1731 /* Finally, actually ascend one level. */
1732 DecodeNesting_Ascend(&(pMe->nesting));
1733 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001734
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001735 uReturn = QCBOR_SUCCESS;
1736
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001737#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001738Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001739#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1740
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001741 return uReturn;
1742}
1743
1744
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001745/**
1746 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1747 *
1748 * @param[in] pMe Decoder context
1749 * @param[out] pDecodedItem The decoded item that work is done on.
1750 *
1751 * @retval QCBOR_ERR_UNSUPPORTED
1752 * @retval QCBOR_ERR_HIT_END
1753 * @retval QCBOR_ERR_INT_OVERFLOW
1754 * @retval QCBOR_ERR_STRING_ALLOCATE
1755 * @retval QCBOR_ERR_STRING_TOO_LONG
1756 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001757 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001758 * @retval QCBOR_ERR_BAD_TYPE_7
1759 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1760 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1761 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1762 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1763 * @retval QCBOR_ERR_TOO_MANY_TAGS
1764 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1765 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1766 * @retval QCBOR_ERR_NO_MORE_ITEMS
1767 * @retval QCBOR_ERR_BAD_BREAK
1768 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1769 *
1770 * This handles the traversal descending into and asecnding out of
1771 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1772 * definite- and indefinte-length maps and arrays by looking at the
1773 * item count or finding CBOR breaks. It detects the ends of the
1774 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001775 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001776static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001777QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001778{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001779 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001780 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001781
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001782 /* If out of bytes to consume, it is either the end of the
1783 * top-level sequence of some bstr-wrapped CBOR that was entered.
1784 *
1785 * In the case of bstr-wrapped CBOR, the length of the
1786 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1787 * the bstr-wrapped CBOR is exited, the length is set back to the
1788 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001789 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001790 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001791 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001792 goto Done;
1793 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001794
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001795 /* Check to see if at the end of a bounded definite-length map or
1796 * array. The check for a break ending indefinite-length array is
1797 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001798 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001799 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001800 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001801 goto Done;
1802 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001803
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001804 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001805 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001806 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1807 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001808 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001809 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301810
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001811 /* Breaks ending arrays/maps are processed later in the call to
1812 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001813 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301814 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001815 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301816 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301817 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001819 /* Record the nesting level for this data item before processing
1820 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001821 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001822 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001823
Laurence Lundblade642282a2020-06-23 12:00:33 -07001824
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001825 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001826 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001827 /* If the new item is a map or array, descend.
1828 *
1829 * Empty indefinite-length maps and arrays are descended into,
1830 * but then ascended out of in the next chunk of code.
1831 *
1832 * Maps and arrays do count as items in the map/array that
1833 * encloses them so a decrement needs to be done for them too,
1834 * but that is done only when all the items in them have been
1835 * processed, not when they are opened with the exception of an
1836 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001837 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001838 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001839 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001840 pDecodedItem->uDataType,
1841 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001842 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001843 /* This error is probably a traversal error and it overrides
1844 * the non-traversal error.
1845 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001846 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001847 goto Done;
1848 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001849 }
1850
Laurence Lundblade02625d42020-06-25 14:41:41 -07001851 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1852 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1853 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001854 /* The following cases are handled here:
1855 * - A non-aggregate item like an integer or string
1856 * - An empty definite-length map or array
1857 * - An indefinite-length map or array that might be empty or might not.
1858 *
1859 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1860 * for an definite-length map/array and break detection for an
1861 * indefinite-0length map/array. If the end of the map/array was
1862 * reached, then it ascends nesting levels, possibly all the way
1863 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001864 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001865 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001866 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001867 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001868 /* This error is probably a traversal error and it overrides
1869 * the non-traversal error.
1870 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001871 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001872 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001873 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301874 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001875
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001876 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001877 /* Tell the caller what level is next. This tells them what
1878 * maps/arrays were closed out and makes it possible for them to
1879 * reconstruct the tree with just the information returned in a
1880 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001881 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001882 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001883 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001884 pDecodedItem->uNextNestLevel = 0;
1885 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001886 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001887 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001888
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001889Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001890 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001891}
1892
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001893
Laurence Lundblade37286c02022-09-03 10:05:02 -07001894#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001895/**
1896 * @brief Shift 0th tag out of the tag list.
1897 *
1898 * pDecodedItem[in,out] The data item to convert.
1899 *
1900 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1901 * shifted into empty slot at the end of the tag list.
1902 */
1903static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001904{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001905 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1906 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1907 }
1908 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001909}
1910
Laurence Lundblade37286c02022-09-03 10:05:02 -07001911#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001912
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001913/**
1914 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1915 *
1916 * pDecodedItem[in,out] The data item to convert.
1917 *
1918 * @retval QCBOR_ERR_DATE_OVERFLOW
1919 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001920 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001921 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001922 *
1923 * The epoch date tag defined in QCBOR allows for floating-point
1924 * dates. It even allows a protocol to flop between date formats when
1925 * ever it wants. Floating-point dates aren't that useful as they are
1926 * only needed for dates beyond the age of the earth.
1927 *
1928 * This converts all the date formats into one format of an unsigned
1929 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001930 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001931static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001932{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001933 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001935#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001936 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001937#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001938
1939 switch (pDecodedItem->uDataType) {
1940
1941 case QCBOR_TYPE_INT64:
1942 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1943 break;
1944
1945 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001946 /* This only happens for CBOR type 0 > INT64_MAX so it is
1947 * always an overflow.
1948 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001949 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1950 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 break;
1952
1953 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001954 case QCBOR_TYPE_FLOAT:
1955#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001956 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001957 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001958 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001959 pDecodedItem->val.dfnum :
1960 (double)pDecodedItem->val.fnum;
1961
1962 /* The conversion from float to integer requires overflow
1963 * detection since floats can be much larger than integers.
1964 * This implementation errors out on these large float values
1965 * since they are beyond the age of the earth.
1966 *
1967 * These constants for the overflow check are computed by the
1968 * compiler. They are not computed at run time.
1969 *
1970 * The factor of 0x7ff is added/subtracted to avoid a
1971 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001972 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001973 * 64-bit integer has 63 bits of precision where a double
1974 * only has 53 bits. Without the 0x7ff factor, the compiler
1975 * may round up and produce a double for the bounds check
1976 * that is larger than can be stored in a 64-bit integer. The
1977 * amount of 0x7ff is picked because it has 11 bits set.
1978 *
1979 * Without the 0x7ff there is a ~30 minute range of time
1980 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001981 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001982 * generate a warning or error without the 0x7ff.
1983 */
1984 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1985 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1986
1987 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001988 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989 goto Done;
1990 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001991
1992 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001993 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001994 pDecodedItem->val.epochDate.fSecondsFraction =
1995 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001997#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001998
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001999 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002000 goto Done;
2001
Laurence Lundblade9682a532020-06-06 18:33:04 -07002002#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003 break;
2004
2005 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002006 /* It's the arrays and maps that are unrecoverable because
2007 * they are not consumed here. Since this is just an error
2008 * condition, no extra code is added here to make the error
2009 * recoverable for non-arrays and maps like strings. */
2010 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002011 goto Done;
2012 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002013
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2015
2016Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002017 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018}
2019
2020
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002021/**
2022 * @brief Convert the days epoch date.
2023 *
2024 * pDecodedItem[in,out] The data item to convert.
2025 *
2026 * @retval QCBOR_ERR_DATE_OVERFLOW
2027 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002028 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002029 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002030 *
2031 * This is much simpler than the other epoch date format because
2032 * floating-porint is not allowed. This is mostly a simple type check.
2033 */
2034static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2035{
2036 QCBORError uReturn = QCBOR_SUCCESS;
2037
2038 switch (pDecodedItem->uDataType) {
2039
2040 case QCBOR_TYPE_INT64:
2041 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2042 break;
2043
2044 case QCBOR_TYPE_UINT64:
2045 /* This only happens for CBOR type 0 > INT64_MAX so it is
2046 * always an overflow.
2047 */
2048 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2049 goto Done;
2050 break;
2051
2052 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002053 /* It's the arrays and maps that are unrecoverable because
2054 * they are not consumed here. Since this is just an error
2055 * condition, no extra code is added here to make the error
2056 * recoverable for non-arrays and maps like strings. */
2057 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002058 goto Done;
2059 break;
2060 }
2061
2062 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2063
2064Done:
2065 return uReturn;
2066}
2067
2068
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002069#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002070
2071/* Forward declaration is necessary for
2072 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2073 * tags in the mantissa. If the mantissa is a decimal fraction or big
2074 * float in error, this will result in a recurive call to
2075 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2076 * correctly and the correct error is returned.
2077 */
2078static QCBORError
2079QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem);
2080
2081
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002082/**
2083 * @brief Decode decimal fractions and big floats.
2084 *
2085 * @param[in] pMe The decode context.
2086 * @param[in,out] pDecodedItem On input the array data item that
2087 * holds the mantissa and exponent. On
2088 * output the decoded mantissa and
2089 * exponent.
2090 *
2091 * @returns Decoding errors from getting primitive data items or
2092 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2093 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002094 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002095 * exponent and mantissa.
2096 *
2097 * This will fetch and decode the exponent and mantissa and put the
2098 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002099 *
2100 * This does no checking or processing of tag numbers. That is to be
2101 * done by the code that calls this.
2102 *
2103 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2104 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002105 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002106static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002107QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002108{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002109 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002110
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002111 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002112 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002113 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 goto Done;
2115 }
2116
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002117 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002118 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002119 * the nesting level the two integers must be at, which is one
2120 * deeper than that of the array.
2121 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2123
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002124 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002125 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002126 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2127 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002128 goto Done;
2129 }
2130 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002131 /* Array is empty or a map/array encountered when expecting an int */
2132 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002133 goto Done;
2134 }
2135 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002136 /* Data arriving as an unsigned int < INT64_MAX has been
2137 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2138 * also means that the only data arriving here of type
2139 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2140 * and thus an error that will get handled in the next else.
2141 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002142 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2143 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002144 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2145 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002146 goto Done;
2147 }
2148
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002149 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002150 QCBORItem mantissaItem;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002151 uReturn = QCBORDecode_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002152 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002153 goto Done;
2154 }
2155 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002156 /* Mantissa missing or map/array encountered when expecting number */
2157 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002158 goto Done;
2159 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002160 /* Stuff the mantissa data type into the item to send it up to the
2161 * the next level. */
2162 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002163 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002164 /* Data arriving as an unsigned int < INT64_MAX has been
2165 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2166 * also means that the only data arriving here of type
2167 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2168 * and thus an error that will get handled in an else below.
2169 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002171#ifndef QCBOR_DISABLE_TAGS
2172 /* With tags fully disabled a big number mantissa will error out
2173 * in the call to QCBORDecode_GetNextWithTags() because it has
2174 * a tag number.
2175 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002176 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2177 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002178 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002179 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002180#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002181 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002182 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2183 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184 goto Done;
2185 }
2186
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002187 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002188 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002189 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002190 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002191 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002192 goto Done;
2193 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002194 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002195
2196Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002197 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002198}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002199#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002200
2201
Laurence Lundblade37286c02022-09-03 10:05:02 -07002202#ifndef QCBOR_DISABLE_TAGS
2203
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002204#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002205/**
2206 * @brief Decode the MIME type tag
2207 *
2208 * @param[in,out] pDecodedItem The item to decode.
2209 *
2210 * Handle the text and binary MIME type tags. Slightly too complicated
2211 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2212 * incorreclty text-only.
2213 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002214static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002215{
2216 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2217 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002218 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002219 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2220 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002221 /* It's the arrays and maps that are unrecoverable because
2222 * they are not consumed here. Since this is just an error
2223 * condition, no extra code is added here to make the error
2224 * recoverable for non-arrays and maps like strings. */
2225 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002226 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002227
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002228 return QCBOR_SUCCESS;
2229}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002230#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002231
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002232/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002233 * Table of CBOR tags whose content is either a text string or a byte
2234 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2235 * of uQCBORtype indicates the content should be a byte string rather
2236 * than a text string
2237 */
2238struct StringTagMapEntry {
2239 uint16_t uTagNumber;
2240 uint8_t uQCBORtype;
2241};
2242
2243#define IS_BYTE_STRING_BIT 0x80
2244#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2245
2246static const struct StringTagMapEntry StringTagMap[] = {
2247 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002248 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002249 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2250 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2251 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2252 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002253#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002254 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2255 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2256 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2257 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002258#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002259 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2260 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2261};
2262
2263
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002264/**
2265 * @brief Process standard CBOR tags whose content is a string
2266 *
2267 * @param[in] uTag The tag.
2268 * @param[in,out] pDecodedItem The data item.
2269 *
2270 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2271 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002272 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002273 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002274 * Process the CBOR tags that whose content is a byte string or a text
2275 * string and for which the string is just passed on to the caller.
2276 *
2277 * This maps the CBOR tag to the QCBOR type and checks the content
2278 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002279 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002280 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002281 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002282static inline QCBORError
2283ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002284{
Laurence Lundblade99615302020-11-29 11:19:47 -08002285 /* This only works on tags that were not mapped; no need for other yet */
2286 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2287 return QCBOR_ERR_UNSUPPORTED;
2288 }
2289
2290 unsigned uIndex;
2291 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2292 if(StringTagMap[uIndex].uTagNumber == uTag) {
2293 break;
2294 }
2295 }
2296
2297 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2298 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002299 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002300 return QCBOR_ERR_UNSUPPORTED;
2301 }
2302
2303 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2304 if(uQCBORType & IS_BYTE_STRING_BIT) {
2305 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2306 }
2307
2308 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002309 /* It's the arrays and maps that are unrecoverable because
2310 * they are not consumed here. Since this is just an error
2311 * condition, no extra code is added here to make the error
2312 * recoverable for non-arrays and maps like strings. */
2313 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002314 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002315
Laurence Lundblade99615302020-11-29 11:19:47 -08002316 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002317 return QCBOR_SUCCESS;
2318}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002319#endif /* QCBOR_DISABLE_TAGS */
2320
2321
2322#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2323/*
2324 * This returns the QCBOR_TYPE for a mantissa and exponent.
2325
2326Called in one context where there is always a tag
2327
2328 Called in another context where there might be a tag or the caller might say what they are expecting.
2329
2330 6 possible outputs
2331 */
2332static inline uint8_t
2333MantissaExponentDataType(const uint16_t uTagToProcess, const QCBORItem *pDecodedItem)
2334{
2335 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2336 QCBOR_TYPE_DECIMAL_FRACTION :
2337 QCBOR_TYPE_BIGFLOAT;
2338 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2339 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2340 }
2341 return uBase;
2342}
2343#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002344
2345
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002346/**
2347 * @brief Decode tag content for select tags (decoding layer 1).
2348 *
2349 * @param[in] pMe The decode context.
2350 * @param[out] pDecodedItem The decoded item.
2351 *
2352 * @return Decoding error code.
2353 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002354 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2355 * but the whole tag was not decoded. Here, the whole tags (tag number
2356 * and tag content) that are supported by QCBOR are decoded. This is a
2357 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002358 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002359static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002360QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002361{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002362 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002363
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002364 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002365 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002366 goto Done;
2367 }
2368
Laurence Lundblade37286c02022-09-03 10:05:02 -07002369#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002370 /* When there are no tag numbers for the item, this exits first
2371 * thing and effectively does nothing.
2372 *
2373 * This loops over all the tag numbers accumulated for this item
2374 * trying to decode and interpret them. This stops at the end of
2375 * the list or at the first tag number that can't be interpreted by
2376 * this code. This is effectively a recursive processing of the
2377 * tags number list that handles nested tags.
2378 */
2379 while(1) {
2380 /* Don't bother to unmap tags via QCBORITem.uTags since this
2381 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2382 */
2383 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002384
Laurence Lundblade99615302020-11-29 11:19:47 -08002385 if(uTagToProcess == CBOR_TAG_INVALID16) {
2386 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002387 break;
2388
Laurence Lundblade99615302020-11-29 11:19:47 -08002389 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002390 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002391
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002392 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2393 uReturn = DecodeDaysEpoch(pDecodedItem);
2394
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002395#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002396 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2397 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002398 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002399 /* --- Which is it, decimal fraction or a bigfloat? --- */
2400 pDecodedItem->uDataType = MantissaExponentDataType(uTagToProcess, pDecodedItem);
2401
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002402#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002403#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002404 } else if(uTagToProcess == CBOR_TAG_MIME ||
2405 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002406 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002407#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002408
Laurence Lundblade99615302020-11-29 11:19:47 -08002409 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002410 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002411 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002412
Laurence Lundblade99615302020-11-29 11:19:47 -08002413 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002414 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002415 * an unknown tag. This is the exit from the loop on the
2416 * first unknown tag. It is a successful exit.
2417 */
2418 uReturn = QCBOR_SUCCESS;
2419 break;
2420 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002421 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002422
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002423 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002424 /* Error exit from the loop */
2425 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002426 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002427
2428 /* A tag was successfully processed, shift it out of the list of
2429 * tags returned. This is the loop increment.
2430 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002431 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002432 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002433#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002434
2435Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002436 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002437}
2438
2439
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002440/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002441 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002442 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002443QCBORError
2444QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2445{
2446 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002447 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002448 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002449 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2450 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2451 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002452 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002453}
2454
2455
2456/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002457 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002458 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002459QCBORError
2460QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2461{
2462 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2463 const UsefulInputBuf Save = pMe->InBuf;
2464
2465 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2466
2467 pMe->nesting = SaveNesting;
2468 pMe->InBuf = Save;
2469
2470 return uErr;
2471}
2472
2473
2474/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002475 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002476 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002477void
2478QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2479{
2480 if(pMe->uLastError != QCBOR_SUCCESS) {
2481 return;
2482 }
2483
2484 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2485}
2486
2487
2488/*
2489 * Public function, see header qcbor/qcbor_decode.h file
2490 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002491void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2492{
2493 if(pMe->uLastError != QCBOR_SUCCESS) {
2494 return;
2495 }
2496
2497 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2498}
2499
2500
2501/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002502 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002503 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002504QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002505QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2506 QCBORItem *pDecodedItem,
2507 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002508{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002509#ifndef QCBOR_DISABLE_TAGS
2510
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002511 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002512
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002513 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2514 if(uReturn != QCBOR_SUCCESS) {
2515 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002516 }
2517
2518 if(pTags != NULL) {
2519 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002520 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002521 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2522 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002523 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002524 }
2525 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2526 return QCBOR_ERR_TOO_MANY_TAGS;
2527 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002528 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002529 pTags->uNumUsed++;
2530 }
2531 }
2532
2533 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002534
2535#else /* QCBOR_DISABLE_TAGS */
2536 (void)pMe;
2537 (void)pDecodedItem;
2538 (void)pTags;
2539 return QCBOR_ERR_TAGS_DISABLED;
2540#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002541}
2542
2543
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002544/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002545 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302546 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002547bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002548 const QCBORItem *pItem,
2549 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002550{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002551#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002552 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2553 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002554 break;
2555 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002556 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002557 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002558 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002559 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002560#else /* QCBOR_TAGS_DISABLED */
2561 (void)pMe;
2562 (void)pItem;
2563 (void)uTag;
2564#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002565
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002566 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002567}
2568
2569
2570/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002571 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002572 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002573QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002574{
Laurence Lundblade87495732021-02-26 10:05:55 -07002575 if(puConsumed != NULL) {
2576 *puConsumed = pMe->InBuf.cursor;
2577 }
2578
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002579 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002580
2581 if(uReturn != QCBOR_SUCCESS) {
2582 goto Done;
2583 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002584
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002585 /* Error out if all the maps/arrays are not closed out */
2586 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002587 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002588 goto Done;
2589 }
2590
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002591 /* Error out if not all the bytes are consumed */
2592 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002593 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002594 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002595
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002596Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002597 return uReturn;
2598}
2599
2600
2601/*
2602 * Public function, see header qcbor/qcbor_decode.h file
2603 */
2604QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2605{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002606#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002607 /* Call the destructor for the string allocator if there is one.
2608 * Always called, even if there are errors; always have to clean up.
2609 */
2610 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002611#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002612
Laurence Lundblade87495732021-02-26 10:05:55 -07002613 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002614}
2615
2616
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002617/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002618 * Public function, see header qcbor/qcbor_decode.h file
2619 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002620// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002621uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2622 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002623 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002624{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002625#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002626 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2627 return CBOR_TAG_INVALID64;
2628 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002629 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2630 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002631 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002632 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002633 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002634#else /* QCBOR_DISABLE_TAGS */
2635 (void)pMe;
2636 (void)pItem;
2637 (void)uIndex;
2638
2639 return CBOR_TAG_INVALID64;
2640#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002641}
2642
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002643
Laurence Lundblade9b334962020-08-27 10:55:53 -07002644/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002645 * Public function, see header qcbor/qcbor_decode.h file
2646 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002647uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2648 uint32_t uIndex)
2649{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002650#ifndef QCBOR_DISABLE_TAGS
2651
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002652 if(pMe->uLastError != QCBOR_SUCCESS) {
2653 return CBOR_TAG_INVALID64;
2654 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002655 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2656 return CBOR_TAG_INVALID64;
2657 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002658 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002659 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002660#else /* QCBOR_DISABLE_TAGS */
2661 (void)pMe;
2662 (void)uIndex;
2663
2664 return CBOR_TAG_INVALID64;
2665#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002666}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002668
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002669
2670
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002671#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002672
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002673/* ===========================================================================
2674 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002675
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002676 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002677 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2678 implements the function type QCBORStringAllocate and allows easy
2679 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002680
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002681 This particular allocator is built-in for convenience. The caller
2682 can implement their own. All of this following code will get
2683 dead-stripped if QCBORDecode_SetMemPool() is not called.
2684
2685 This is a very primitive memory allocator. It does not track
2686 individual allocations, only a high-water mark. A free or
2687 reallocation must be of the last chunk allocated.
2688
2689 The size of the pool and offset to free memory are packed into the
2690 first 8 bytes of the memory pool so we don't have to keep them in
2691 the decode context. Since the address of the pool may not be
2692 aligned, they have to be packed and unpacked as if they were
2693 serialized data of the wire or such.
2694
2695 The sizes packed in are uint32_t to be the same on all CPU types
2696 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002697 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002698
2699
Laurence Lundbladeee851742020-01-08 08:37:05 -08002700static inline int
2701MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002702{
2703 // Use of UsefulInputBuf is overkill, but it is convenient.
2704 UsefulInputBuf UIB;
2705
Laurence Lundbladeee851742020-01-08 08:37:05 -08002706 // Just assume the size here. It was checked during SetUp so
2707 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002708 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002709 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2710 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2711 return UsefulInputBuf_GetError(&UIB);
2712}
2713
2714
Laurence Lundbladeee851742020-01-08 08:37:05 -08002715static inline int
2716MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002717{
2718 // Use of UsefulOutBuf is overkill, but convenient. The
2719 // length check performed here is useful.
2720 UsefulOutBuf UOB;
2721
2722 UsefulOutBuf_Init(&UOB, Pool);
2723 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2724 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2725 return UsefulOutBuf_GetError(&UOB);
2726}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002727
2728
2729/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002730 Internal function for an allocation, reallocation free and destuct.
2731
2732 Having only one function rather than one each per mode saves space in
2733 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002734
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002735 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2736 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002737static UsefulBuf
2738MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002739{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002740 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002741
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002742 uint32_t uPoolSize;
2743 uint32_t uFreeOffset;
2744
2745 if(uNewSize > UINT32_MAX) {
2746 // This allocator is only good up to 4GB. This check should
2747 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2748 goto Done;
2749 }
2750 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2751
2752 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2753 goto Done;
2754 }
2755
2756 if(uNewSize) {
2757 if(pMem) {
2758 // REALLOCATION MODE
2759 // Calculate pointer to the end of the memory pool. It is
2760 // assumed that pPool + uPoolSize won't wrap around by
2761 // assuming the caller won't pass a pool buffer in that is
2762 // not in legitimate memory space.
2763 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2764
2765 // Check that the pointer for reallocation is in the range of the
2766 // pool. This also makes sure that pointer math further down
2767 // doesn't wrap under or over.
2768 if(pMem >= pPool && pMem < pPoolEnd) {
2769 // Offset to start of chunk for reallocation. This won't
2770 // wrap under because of check that pMem >= pPool. Cast
2771 // is safe because the pool is always less than UINT32_MAX
2772 // because of check in QCBORDecode_SetMemPool().
2773 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2774
2775 // Check to see if the allocation will fit. uPoolSize -
2776 // uMemOffset will not wrap under because of check that
2777 // pMem is in the range of the uPoolSize by check above.
2778 if(uNewSize <= uPoolSize - uMemOffset) {
2779 ReturnValue.ptr = pMem;
2780 ReturnValue.len = uNewSize;
2781
2782 // Addition won't wrap around over because uNewSize was
2783 // checked to be sure it is less than the pool size.
2784 uFreeOffset = uMemOffset + uNewSize32;
2785 }
2786 }
2787 } else {
2788 // ALLOCATION MODE
2789 // uPoolSize - uFreeOffset will not underflow because this
2790 // pool implementation makes sure uFreeOffset is always
2791 // smaller than uPoolSize through this check here and
2792 // reallocation case.
2793 if(uNewSize <= uPoolSize - uFreeOffset) {
2794 ReturnValue.len = uNewSize;
2795 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002796 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002797 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002798 }
2799 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002800 if(pMem) {
2801 // FREE MODE
2802 // Cast is safe because of limit on pool size in
2803 // QCBORDecode_SetMemPool()
2804 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2805 } else {
2806 // DESTRUCT MODE
2807 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002808 }
2809 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002810
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002811 UsefulBuf Pool = {pPool, uPoolSize};
2812 MemPool_Pack(Pool, uFreeOffset);
2813
2814Done:
2815 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002816}
2817
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002818
Laurence Lundbladef6531662018-12-04 10:42:22 +09002819/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002820 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002821 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002822QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2823 UsefulBuf Pool,
2824 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002825{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002826 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002827 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002828 // constant in the header is correct. This check should optimize
2829 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002830#ifdef _MSC_VER
2831#pragma warning(push)
2832#pragma warning(disable:4127) // conditional expression is constant
2833#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002834 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002835 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002836 }
Dave Thaler93c01182022-08-06 15:08:35 -04002837#ifdef _MSC_VER
2838#pragma warning(pop)
2839#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002840
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002841 // The pool size and free offset packed in to the beginning of pool
2842 // memory are only 32-bits. This check will optimize out on 32-bit
2843 // machines.
2844 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002845 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002847
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002848 // This checks that the pool buffer given is big enough.
2849 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002850 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002851 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002852
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002853 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002854
Laurence Lundblade30816f22018-11-10 13:40:22 +07002855 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002856}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002857#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002858
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002859
2860
Laurence Lundblade37286c02022-09-03 10:05:02 -07002861static inline void
2862CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002863{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002864#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002865 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002866#else
2867 (void)pMe;
2868 (void)pItem;
2869#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002870}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002871
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002872
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002873/**
2874 * @brief Consume an entire map or array including its contents.
2875 *
2876 * @param[in] pMe The decoder context.
2877 * @param[in] pItemToConsume The array/map whose contents are to be
2878 * consumed.
2879 * @param[out] puNextNestLevel The next nesting level after the item was
2880 * fully consumed.
2881 *
2882 * This may be called when @c pItemToConsume is not an array or
2883 * map. In that case, this is just a pass through for @c puNextNestLevel
2884 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002885 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002886static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002887ConsumeItem(QCBORDecodeContext *pMe,
2888 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002889 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002890{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002891 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002892 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002893
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002894 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002895 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2896
2897 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2898 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002899
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002900 /* This works for definite- and indefinite-length maps and
2901 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002902 */
2903 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002904 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002905 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2906 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002907 goto Done;
2908 }
2909 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002910
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002911 *puNextNestLevel = Item.uNextNestLevel;
2912
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002913 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002914
Laurence Lundblade1341c592020-04-11 14:19:05 -07002915 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002916 /* pItemToConsume is not a map or array. Just pass the nesting
2917 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002918 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2919
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002920 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002921 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002922
2923Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002924 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002925}
2926
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002927
2928void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2929{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002930 QCBORDecode_VGetNext(pMe, pDecodedItem);
2931
2932 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002933 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2934 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002935 }
2936}
2937
2938
2939
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002940/* Call only on maps and arrays. Rewinds the cursor
2941 * to the start as if it was just entered.
2942 */
2943static void RewindMapOrArray(QCBORDecodeContext *pMe)
2944{
2945 /* Reset nesting tracking to the deepest bounded level */
2946 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2947
2948 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2949
2950 /* Reposition traversal cursor to the start of the map/array */
2951 UsefulInputBuf_Seek(&(pMe->InBuf),
2952 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2953}
2954
2955
2956/*
2957 Public function, see header qcbor/qcbor_decode.h file
2958 */
2959void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2960{
2961 if(pMe->nesting.pCurrentBounded != NULL) {
2962 /* In a bounded map, array or bstr-wrapped CBOR */
2963
2964 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2965 /* In bstr-wrapped CBOR. */
2966
2967 /* Reposition traversal cursor to start of wrapping byte string */
2968 UsefulInputBuf_Seek(&(pMe->InBuf),
2969 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2970 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2971
2972 } else {
2973 /* In a map or array */
2974 RewindMapOrArray(pMe);
2975 }
2976
2977 } else {
2978 /* Not in anything bounded */
2979
2980 /* Reposition traversal cursor to the start of input CBOR */
2981 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2982
2983 /* Reset nesting tracking to beginning of input. */
2984 DecodeNesting_Init(&(pMe->nesting));
2985 }
2986
2987 pMe->uLastError = QCBOR_SUCCESS;
2988}
2989
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002990
Laurence Lundblade1341c592020-04-11 14:19:05 -07002991/* Return true if the labels in Item1 and Item2 are the same.
2992 Works only for integer and string labels. Returns false
2993 for any other type. */
2994static inline bool
2995MatchLabel(QCBORItem Item1, QCBORItem Item2)
2996{
2997 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2998 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2999 return true;
3000 }
3001 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003002 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003003 return true;
3004 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003005 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003006 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
3007 return true;
3008 }
3009 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
3010 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
3011 return true;
3012 }
3013 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003014
Laurence Lundblade1341c592020-04-11 14:19:05 -07003015 /* Other label types are never matched */
3016 return false;
3017}
3018
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003019
3020/*
3021 Returns true if Item1 and Item2 are the same type
3022 or if either are of QCBOR_TYPE_ANY.
3023 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003024static inline bool
3025MatchType(QCBORItem Item1, QCBORItem Item2)
3026{
3027 if(Item1.uDataType == Item2.uDataType) {
3028 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003029 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003030 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003031 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003032 return true;
3033 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003034 return false;
3035}
3036
3037
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003038/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003039 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003040
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003041 @param[in] pMe The decode context to search.
3042 @param[in,out] pItemArray The items to search for and the items found.
3043 @param[out] puOffset Byte offset of last item matched.
3044 @param[in] pCBContext Context for the not-found item call back.
3045 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003046
3047 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3048
Laurence Lundblade93d89472020-10-03 22:30:50 -07003049 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3050 were found for one of the labels being
3051 search for. This duplicate detection is
3052 only performed for items in pItemArray,
3053 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003054
Laurence Lundblade93d89472020-10-03 22:30:50 -07003055 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3056 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003057
3058 @retval Also errors returned by QCBORDecode_GetNext().
3059
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003060 On input pItemArray contains a list of labels and data types
3061 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003062
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003063 On output the fully retrieved items are filled in with
3064 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003065
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003066 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003067
3068 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003069 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003070static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003071MapSearch(QCBORDecodeContext *pMe,
3072 QCBORItem *pItemArray,
3073 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003074 void *pCBContext,
3075 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003076{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003077 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003078 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003079
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003080 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003081 uReturn = pMe->uLastError;
3082 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003083 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003084
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003085 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003086 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3087 /* QCBOR_TYPE_NONE as first item indicates just looking
3088 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003089 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3090 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003091 }
3092
Laurence Lundblade085d7952020-07-24 10:26:30 -07003093 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3094 // It is an empty bounded array or map
3095 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3096 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003097 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003098 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003099 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003100 // Nothing is ever found in an empty array or map. All items
3101 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003102 uReturn = QCBOR_SUCCESS;
3103 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003104 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003105 }
3106
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003107 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003108 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3109
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003110 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003111 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003112
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003113 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003114 Loop over all the items in the map or array. Each item
3115 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003116 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003117 length maps and arrays. The only reason this is ever
3118 called on arrays is to find their end position.
3119
3120 This will always run over all items in order to do
3121 duplicate detection.
3122
3123 This will exit with failure if it encounters an
3124 unrecoverable error, but continue on for recoverable
3125 errors.
3126
3127 If a recoverable error occurs on a matched item, then
3128 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003129 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003130 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003131 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003132 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003133 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003134 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003135
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003136 /* Get the item */
3137 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003138 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003139 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003140 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003141 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003142 goto Done;
3143 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003144 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003145 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003146 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003147 goto Done;
3148 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003149
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003150 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003151 bool bMatched = false;
3152 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3153 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003154 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003155 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3156 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003157 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003158 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003159 if(uResult != QCBOR_SUCCESS) {
3160 /* The label matches, but the data item is in error */
3161 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003162 goto Done;
3163 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003164 if(!MatchType(Item, pItemArray[nIndex])) {
3165 /* The data item is not of the type(s) requested */
3166 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003167 goto Done;
3168 }
3169
Laurence Lundblade1341c592020-04-11 14:19:05 -07003170 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003171 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003172 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003173 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003174 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003175 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003176 bMatched = true;
3177 }
3178 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003179
3180
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003181 if(!bMatched && pfCallback != NULL) {
3182 /*
3183 Call the callback on unmatched labels.
3184 (It is tempting to do duplicate detection here, but that would
3185 require dynamic memory allocation because the number of labels
3186 that might be encountered is unbounded.)
3187 */
3188 uReturn = (*pfCallback)(pCBContext, &Item);
3189 if(uReturn != QCBOR_SUCCESS) {
3190 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003191 }
3192 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003193
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003194 /*
3195 Consume the item whether matched or not. This
3196 does the work of traversing maps and array and
3197 everything in them. In this loop only the
3198 items at the current nesting level are examined
3199 to match the labels.
3200 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003201 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003202 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003203 goto Done;
3204 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003205
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003206 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003207
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003208 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003209
3210 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003211
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003212 // Check here makes sure that this won't accidentally be
3213 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003214 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003215 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3216 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003217 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3218 goto Done;
3219 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003220 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3221 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003222
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003223 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003224 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3225
3226 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003227 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003228 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003229 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003230 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3231 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003232 }
3233 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003234
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003235 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003236}
3237
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003238
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003239/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003240 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003241*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003242void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3243 int64_t nLabel,
3244 uint8_t uQcborType,
3245 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003246{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003247 if(pMe->uLastError != QCBOR_SUCCESS) {
3248 return;
3249 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003250
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003251 QCBORItem OneItemSeach[2];
3252 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3253 OneItemSeach[0].label.int64 = nLabel;
3254 OneItemSeach[0].uDataType = uQcborType;
3255 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003256
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003257 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003258
3259 *pItem = OneItemSeach[0];
3260
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003261 if(uReturn != QCBOR_SUCCESS) {
3262 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003263 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003264 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003265 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003266 }
3267
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003268 Done:
3269 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003270}
3271
3272
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003273/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003274 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003275*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003276void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3277 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003278 uint8_t uQcborType,
3279 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003280{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003281 if(pMe->uLastError != QCBOR_SUCCESS) {
3282 return;
3283 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003284
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003285 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003286 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3287 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3288 OneItemSeach[0].uDataType = uQcborType;
3289 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003290
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003291 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3292 if(uReturn != QCBOR_SUCCESS) {
3293 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003294 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003295 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003296 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003297 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003298 }
3299
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003300 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003301
3302Done:
3303 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003304}
3305
3306
Laurence Lundblade93d89472020-10-03 22:30:50 -07003307static QCBORError
3308CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003309{
3310 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3311 if(uDataType == puTypeList[i]) {
3312 return QCBOR_SUCCESS;
3313 }
3314 }
3315 return QCBOR_ERR_UNEXPECTED_TYPE;
3316}
3317
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003318
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003319/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003320 * Match a tag/type specification against the type of the item.
3321 *
3322 * @param[in] TagSpec Specification for matching tags.
3323 * @param[in] pItem The item to check.
3324 *
3325 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3326 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3327 *
3328 * This checks the item data type of untagged items as well as of
3329 * tagged items against a specification to see if decoding should
3330 * proceed.
3331 *
3332 * This relies on the automatic tag decoding done by QCBOR that turns
3333 * tag numbers into particular QCBOR_TYPEs so there is no actual
3334 * comparsion of tag numbers, just of QCBOR_TYPEs.
3335 *
3336 * This checks the data item type as possibly representing the tag
3337 * number or as the tag content type.
3338 *
3339 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3340 * data type against the allowed tag content types. It will also error out
3341 * if the caller tries to require a tag because there is no way that can
3342 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003343 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003344static QCBORError
3345CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003346{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003347 const int nItemType = pItem->uDataType;
3348 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3349
3350#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003351 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3352 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3353 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003354 * the caller has told us there should not be.
3355 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003356 return QCBOR_ERR_UNEXPECTED_TYPE;
3357 }
3358
Laurence Lundblade9b334962020-08-27 10:55:53 -07003359 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003360 /* Must match the tag number and only the tag */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003361 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3362 }
3363
3364 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3365 if(uReturn == QCBOR_SUCCESS) {
3366 return QCBOR_SUCCESS;
3367 }
3368
3369 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3370 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003371 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003372 return QCBOR_ERR_UNEXPECTED_TYPE;
3373 }
3374
Laurence Lundblade37286c02022-09-03 10:05:02 -07003375 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3376 * and it hasn't matched the content, so the end
3377 * result is whether it matches the tag. This is
3378 * the tag optional case that the CBOR standard discourages.
3379 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003380
3381 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003382
Laurence Lundblade37286c02022-09-03 10:05:02 -07003383#else /* QCBOR_DISABLE_TAGS */
3384 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3385 return QCBOR_ERR_UNEXPECTED_TYPE;
3386 }
3387
3388 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3389
3390#endif /* QCBOR_DISABLE_TAGS */
3391}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003392
Laurence Lundblade9b334962020-08-27 10:55:53 -07003393
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003394// This could be semi-private if need be
3395static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003396void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3397 const int64_t nLabel,
3398 const TagSpecification TagSpec,
3399 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003400{
3401 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3402 if(pMe->uLastError != QCBOR_SUCCESS) {
3403 return;
3404 }
3405
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003406 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003407}
3408
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003409
3410// This could be semi-private if need be
3411static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003412void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3413 const char *szLabel,
3414 const TagSpecification TagSpec,
3415 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003416{
3417 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3418 if(pMe->uLastError != QCBOR_SUCCESS) {
3419 return;
3420 }
3421
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003422 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003423}
3424
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003425// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003426void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3427 int64_t nLabel,
3428 TagSpecification TagSpec,
Laurence Lundblade37286c02022-09-03 10:05:02 -07003429 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003430{
3431 QCBORItem Item;
3432 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3433 if(pMe->uLastError == QCBOR_SUCCESS) {
3434 *pString = Item.val.string;
3435 }
3436}
3437
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003438// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003439void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3440 const char * szLabel,
3441 TagSpecification TagSpec,
3442 UsefulBufC *pString)
3443{
3444 QCBORItem Item;
3445 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3446 if(pMe->uLastError == QCBOR_SUCCESS) {
3447 *pString = Item.val.string;
3448 }
3449}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003450
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003451/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003452 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003453*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003454void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003455{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003456 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3457 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003458}
3459
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003460/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003461 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003462*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003463void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3464 QCBORItem *pItemList,
3465 void *pCallbackCtx,
3466 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003467{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003468 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3469 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003470}
3471
3472
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003473/**
3474 * @brief Search for a map/array by label and enter it
3475 *
3476 * @param[in] pMe The decode context.
3477 * @param[in] pSearch The map/array to search for.
3478 *
3479 * @c pSearch is expected to contain one item of type map or array
3480 * with the label specified. The current bounded map will be searched for
3481 * this and if found will be entered.
3482 *
3483 * If the label is not found, or the item found is not a map or array,
3484 * the error state is set.
3485 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003486static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003487{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003488 // The first item in pSearch is the one that is to be
3489 // entered. It should be the only one filled in. Any other
3490 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003491 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003492 return;
3493 }
3494
3495 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003496 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003497 if(pMe->uLastError != QCBOR_SUCCESS) {
3498 return;
3499 }
3500
Laurence Lundblade9b334962020-08-27 10:55:53 -07003501 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003502 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003503 return;
3504 }
3505
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003506
3507 /* The map or array was found. Now enter it.
3508 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003509 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3510 * next item for the pre-order traversal cursor to be the map/array
3511 * found by MapSearch(). The next few lines of code force the
3512 * cursor to that.
3513 *
3514 * There is no need to retain the old cursor because
3515 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3516 * beginning of the map/array being entered.
3517 *
3518 * The cursor is forced by: 1) setting the input buffer position to
3519 * the item offset found by MapSearch(), 2) setting the map/array
3520 * counter to the total in the map/array, 3) setting the nesting
3521 * level. Setting the map/array counter to the total is not
3522 * strictly correct, but this is OK because this cursor only needs
3523 * to be used to get one item and MapSearch() has already found it
3524 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003525 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003526 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003527
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003528 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3529
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003530 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003531
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003532 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003533}
3534
3535
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003536/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003537 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003538*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003539void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003540{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003541 QCBORItem OneItemSeach[2];
3542 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3543 OneItemSeach[0].label.int64 = nLabel;
3544 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3545 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003546
Laurence Lundblade9b334962020-08-27 10:55:53 -07003547 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003548 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003549}
3550
3551
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003552/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003553 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003554*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003555void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003556{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003557 QCBORItem OneItemSeach[2];
3558 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3559 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3560 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3561 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003562
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003563 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003564}
3565
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003566/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003567 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003568*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003569void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003570{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003571 QCBORItem OneItemSeach[2];
3572 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3573 OneItemSeach[0].label.int64 = nLabel;
3574 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3575 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003576
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003577 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003578}
3579
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003580/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003581 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003582*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003583void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3584{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003585 QCBORItem OneItemSeach[2];
3586 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3587 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3588 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3589 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003590
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003591 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003592}
3593
3594
Laurence Lundblade02625d42020-06-25 14:41:41 -07003595// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003596void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003597{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003598 QCBORError uErr;
3599
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003600 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003601 if(pMe->uLastError != QCBOR_SUCCESS) {
3602 // Already in error state; do nothing.
3603 return;
3604 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003605
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003606 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003607 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003608 uErr = QCBORDecode_GetNext(pMe, &Item);
3609 if(uErr != QCBOR_SUCCESS) {
3610 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003611 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003612 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003613 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3614 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003615 }
3616
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003617 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003618
3619
Laurence Lundbladef0499502020-08-01 11:55:57 -07003620 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003621 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003622 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3623 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003624 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003625 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3626 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003627 // Special case to increment nesting level for zero-length maps
3628 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003629 DecodeNesting_Descend(&(pMe->nesting), uType);
3630 }
3631
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003632 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003633
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003634 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3635 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003636
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003637 if(pItem != NULL) {
3638 *pItem = Item;
3639 }
3640
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003641Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003642 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003643}
3644
Laurence Lundblade02625d42020-06-25 14:41:41 -07003645
3646/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003647 This is the common work for exiting a level that is a bounded map,
3648 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003649
3650 One chunk of work is to set up the pre-order traversal so it is at
3651 the item just after the bounded map, array or bstr that is being
3652 exited. This is somewhat complex.
3653
3654 The other work is to level-up the bounded mode to next higest bounded
3655 mode or the top level if there isn't one.
3656 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003657static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003658ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003659{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003660 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003661
Laurence Lundblade02625d42020-06-25 14:41:41 -07003662 /*
3663 First the pre-order-traversal byte offset is positioned to the
3664 item just after the bounded mode item that was just consumed.
3665 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003666 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3667
Laurence Lundblade02625d42020-06-25 14:41:41 -07003668 /*
3669 Next, set the current nesting level to one above the bounded level
3670 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003671
Laurence Lundblade02625d42020-06-25 14:41:41 -07003672 DecodeNesting_CheckBoundedType() is always called before this and
3673 makes sure pCurrentBounded is valid.
3674 */
3675 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3676
3677 /*
3678 This does the complex work of leveling up the pre-order traversal
3679 when the end of a map or array or another bounded level is
3680 reached. It may do nothing, or ascend all the way to the top
3681 level.
3682 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003683 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003684 if(uErr != QCBOR_SUCCESS) {
3685 goto Done;
3686 }
3687
Laurence Lundblade02625d42020-06-25 14:41:41 -07003688 /*
3689 This makes the next highest bounded level the current bounded
3690 level. If there is no next highest level, then no bounded mode is
3691 in effect.
3692 */
3693 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003694
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003695 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003696
3697Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003698 return uErr;
3699}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003700
Laurence Lundblade02625d42020-06-25 14:41:41 -07003701
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003702// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003703void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003704{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003705 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003706 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003707 return;
3708 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003709
Laurence Lundblade02625d42020-06-25 14:41:41 -07003710 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003711
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003712 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003713 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003714 goto Done;
3715 }
3716
Laurence Lundblade02625d42020-06-25 14:41:41 -07003717 /*
3718 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003719 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003720 from previous map search, then do a dummy search.
3721 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003722 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003723 QCBORItem Dummy;
3724 Dummy.uLabelType = QCBOR_TYPE_NONE;
3725 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3726 if(uErr != QCBOR_SUCCESS) {
3727 goto Done;
3728 }
3729 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003730
Laurence Lundblade02625d42020-06-25 14:41:41 -07003731 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003732
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003733Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003734 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003735}
3736
3737
Laurence Lundblade1341c592020-04-11 14:19:05 -07003738
Laurence Lundblade37286c02022-09-03 10:05:02 -07003739static QCBORError
3740InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
3741 const QCBORItem *pItem,
3742 const uint8_t uTagRequirement,
3743 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003744{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003745 if(pBstr) {
3746 *pBstr = NULLUsefulBufC;
3747 }
3748
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003749 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003750 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003751 return pMe->uLastError;
3752 }
3753
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003754 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003755
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003756 const TagSpecification TagSpec =
3757 {
3758 uTagRequirement,
3759 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3760 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3761 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003762
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003763 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003764 if(uError != QCBOR_SUCCESS) {
3765 goto Done;
3766 }
3767
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003768 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003769 /* Reverse the decrement done by GetNext() for the bstr so the
3770 * increment in QCBORDecode_NestLevelAscender() called by
3771 * ExitBoundedLevel() will work right.
3772 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003773 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003774 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003775
3776 if(pBstr) {
3777 *pBstr = pItem->val.string;
3778 }
3779
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003780 /* This saves the current length of the UsefulInputBuf and then
3781 * narrows the UsefulInputBuf to start and length of the wrapped
3782 * CBOR that is being entered.
3783 *
3784 * Most of these calls are simple inline accessors so this doesn't
3785 * amount to much code.
3786 */
3787
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003788 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003789 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3790 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003791 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003792 goto Done;
3793 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003794
3795 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3796 pItem->val.string.ptr);
3797 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3798 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3799 /* This should never happen because pItem->val.string.ptr should
3800 * always be valid since it was just returned.
3801 */
3802 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3803 goto Done;
3804 }
3805
3806 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3807
3808 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003809 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003810
Laurence Lundblade02625d42020-06-25 14:41:41 -07003811 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003812 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003813 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003814Done:
3815 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003816}
3817
3818
Laurence Lundblade02625d42020-06-25 14:41:41 -07003819/*
3820 Public function, see header qcbor/qcbor_decode.h file
3821 */
3822void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003823 uint8_t uTagRequirement,
3824 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003825{
3826 if(pMe->uLastError != QCBOR_SUCCESS) {
3827 // Already in error state; do nothing.
3828 return;
3829 }
3830
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003831 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003832 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003833 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3834 if(pMe->uLastError != QCBOR_SUCCESS) {
3835 return;
3836 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003837
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003838 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003839 &Item,
3840 uTagRequirement,
3841 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003842}
3843
3844
Laurence Lundblade02625d42020-06-25 14:41:41 -07003845/*
3846 Public function, see header qcbor/qcbor_decode.h file
3847 */
3848void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003849 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003850 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003851 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003852{
3853 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003854 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003855
Laurence Lundblade93d89472020-10-03 22:30:50 -07003856 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3857 &Item,
3858 uTagRequirement,
3859 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003860}
3861
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003862
Laurence Lundblade02625d42020-06-25 14:41:41 -07003863/*
3864 Public function, see header qcbor/qcbor_decode.h file
3865 */
3866void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003867 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003868 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003869 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003870{
3871 QCBORItem Item;
3872 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3873
Laurence Lundblade93d89472020-10-03 22:30:50 -07003874 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3875 &Item,
3876 uTagRequirement,
3877 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003878}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003879
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003880
Laurence Lundblade02625d42020-06-25 14:41:41 -07003881/*
3882 Public function, see header qcbor/qcbor_decode.h file
3883 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003884void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003885{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003886 if(pMe->uLastError != QCBOR_SUCCESS) {
3887 // Already in error state; do nothing.
3888 return;
3889 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003890
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003891 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003892 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003893 return;
3894 }
3895
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003896 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3897
Laurence Lundblade02625d42020-06-25 14:41:41 -07003898 /*
3899 Reset the length of the UsefulInputBuf to what it was before
3900 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003901 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003902 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003903 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003904
3905
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003906 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003907 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003908}
3909
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003910
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003912
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003913static inline void
3914ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003915{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003916 if(pMe->uLastError != QCBOR_SUCCESS) {
3917 /* Already in error state, do nothing */
3918 return;
3919 }
3920
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003921 switch(pItem->uDataType) {
3922 case QCBOR_TYPE_TRUE:
3923 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003924 break;
3925
3926 case QCBOR_TYPE_FALSE:
3927 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003928 break;
3929
3930 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003931 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003932 break;
3933 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003934 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003935}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003937
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003938/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003939 * Public function, see header qcbor/qcbor_decode.h file
3940 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003941void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003942{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003943 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003944 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003945 return;
3946 }
3947
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948 QCBORItem Item;
3949
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003950 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3951
3952 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003953}
3954
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003955
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003956/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003957 * Public function, see header qcbor/qcbor_decode.h file
3958 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003959void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003960{
3961 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003962 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003963
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003964 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003965}
3966
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003967
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003968/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003969 * Public function, see header qcbor/qcbor_decode.h file
3970 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003971void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3972{
3973 QCBORItem Item;
3974 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3975
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003976 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003977}
3978
3979
3980
Laurence Lundbladec7114722020-08-13 05:11:40 -07003981
3982static void ProcessEpochDate(QCBORDecodeContext *pMe,
3983 QCBORItem *pItem,
Laurence Lundblade37286c02022-09-03 10:05:02 -07003984 const uint8_t uTagRequirement,
Laurence Lundbladec7114722020-08-13 05:11:40 -07003985 int64_t *pnTime)
3986{
3987 if(pMe->uLastError != QCBOR_SUCCESS) {
3988 // Already in error state, do nothing
3989 return;
3990 }
3991
3992 QCBORError uErr;
3993
3994 const TagSpecification TagSpec =
3995 {
3996 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003997 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3998 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003999 };
4000
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004001 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004002 if(uErr != QCBOR_SUCCESS) {
4003 goto Done;
4004 }
4005
4006 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
4007 uErr = DecodeDateEpoch(pItem);
4008 if(uErr != QCBOR_SUCCESS) {
4009 goto Done;
4010 }
4011 }
4012
Laurence Lundblade9b334962020-08-27 10:55:53 -07004013 // Save the tags in the last item's tags in the decode context
4014 // for QCBORDecode_GetNthTagOfLast()
4015 CopyTags(pMe, pItem);
4016
Laurence Lundbladec7114722020-08-13 05:11:40 -07004017 *pnTime = pItem->val.epochDate.nSeconds;
4018
4019Done:
4020 pMe->uLastError = (uint8_t)uErr;
4021}
4022
4023
4024void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004025 uint8_t uTagRequirement,
4026 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004027{
4028 if(pMe->uLastError != QCBOR_SUCCESS) {
4029 // Already in error state, do nothing
4030 return;
4031 }
4032
4033 QCBORItem Item;
4034 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4035
4036 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4037}
4038
4039
4040void
4041QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4042 int64_t nLabel,
4043 uint8_t uTagRequirement,
4044 int64_t *pnTime)
4045{
4046 QCBORItem Item;
4047 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4048 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4049}
4050
4051
4052void
4053QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4054 const char *szLabel,
4055 uint8_t uTagRequirement,
4056 int64_t *pnTime)
4057{
4058 QCBORItem Item;
4059 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4060 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4061}
4062
4063
4064
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004065/*
4066 * Common processing for the RFC 8943 day-count tag. Mostly
4067 * make sure the tag content is correct and copy forward any
4068 * further other tag numbers.
4069 */
4070static void ProcessEpochDays(QCBORDecodeContext *pMe,
4071 QCBORItem *pItem,
4072 uint8_t uTagRequirement,
4073 int64_t *pnDays)
4074{
4075 if(pMe->uLastError != QCBOR_SUCCESS) {
4076 /* Already in error state, do nothing */
4077 return;
4078 }
4079
4080 QCBORError uErr;
4081
4082 const TagSpecification TagSpec =
4083 {
4084 uTagRequirement,
4085 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4086 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4087 };
4088
4089 uErr = CheckTagRequirement(TagSpec, pItem);
4090 if(uErr != QCBOR_SUCCESS) {
4091 goto Done;
4092 }
4093
4094 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
4095 uErr = DecodeDaysEpoch(pItem);
4096 if(uErr != QCBOR_SUCCESS) {
4097 goto Done;
4098 }
4099 }
4100
4101 /* Save the tags in the last item's tags in the decode context
4102 * for QCBORDecode_GetNthTagOfLast()
4103 */
4104 CopyTags(pMe, pItem);
4105
4106 *pnDays = pItem->val.epochDays;
4107
4108Done:
4109 pMe->uLastError = (uint8_t)uErr;
4110}
4111
4112
4113/*
4114 * Public function, see header qcbor/qcbor_decode.h
4115 */
4116void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4117 uint8_t uTagRequirement,
4118 int64_t *pnDays)
4119{
4120 if(pMe->uLastError != QCBOR_SUCCESS) {
4121 /* Already in error state, do nothing */
4122 return;
4123 }
4124
4125 QCBORItem Item;
4126 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4127
4128 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4129}
4130
4131
4132/*
4133 * Public function, see header qcbor/qcbor_decode.h
4134 */
4135void
4136QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4137 int64_t nLabel,
4138 uint8_t uTagRequirement,
4139 int64_t *pnDays)
4140{
4141 QCBORItem Item;
4142 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4143 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4144}
4145
4146
4147/*
4148 * Public function, see header qcbor/qcbor_decode.h
4149 */
4150void
4151QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4152 const char *szLabel,
4153 uint8_t uTagRequirement,
4154 int64_t *pnDays)
4155{
4156 QCBORItem Item;
4157 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4158 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4159}
4160
4161
4162
Laurence Lundblade37286c02022-09-03 10:05:02 -07004163/*
4164 * @brief Get a string that matches the type/tag specification.
4165 */
4166void
4167QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4168 const TagSpecification TagSpec,
4169 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004170{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004171 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004172 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004173 return;
4174 }
4175
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004176 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004177 QCBORItem Item;
4178
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004179 uError = QCBORDecode_GetNext(pMe, &Item);
4180 if(uError != QCBOR_SUCCESS) {
4181 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004182 return;
4183 }
4184
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004185 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186
4187 if(pMe->uLastError == QCBOR_SUCCESS) {
4188 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004189 } else {
4190 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004191 }
4192}
4193
Laurence Lundbladec4537442020-04-14 18:53:22 -07004194
4195
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004196
Laurence Lundblade37286c02022-09-03 10:05:02 -07004197static QCBORError
4198ProcessBigNum(const uint8_t uTagRequirement,
4199 const QCBORItem *pItem,
4200 UsefulBufC *pValue,
4201 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004202{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004203 const TagSpecification TagSpec =
4204 {
4205 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004206 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4207 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004208 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004209
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004210 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004211 if(uErr != QCBOR_SUCCESS) {
4212 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004214
4215 *pValue = pItem->val.string;
4216
4217 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4218 *pbIsNegative = false;
4219 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4220 *pbIsNegative = true;
4221 }
4222
4223 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004224}
4225
4226
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004227/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004228 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004229 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004230void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4231 uint8_t uTagRequirement,
4232 UsefulBufC *pValue,
4233 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004234{
4235 if(pMe->uLastError != QCBOR_SUCCESS) {
4236 // Already in error state, do nothing
4237 return;
4238 }
4239
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004240 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004241 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4242 if(uError != QCBOR_SUCCESS) {
4243 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004244 return;
4245 }
4246
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004247 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004248}
4249
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004250
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004251/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004252 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004253*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004254void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4255 int64_t nLabel,
4256 uint8_t uTagRequirement,
4257 UsefulBufC *pValue,
4258 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004259{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004260 QCBORItem Item;
4261 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004262 if(pMe->uLastError != QCBOR_SUCCESS) {
4263 return;
4264 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004265
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004266 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004267}
4268
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004269
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004270/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004271 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004272*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004273void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4274 const char *szLabel,
4275 uint8_t uTagRequirement,
4276 UsefulBufC *pValue,
4277 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004278{
4279 QCBORItem Item;
4280 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004281 if(pMe->uLastError != QCBOR_SUCCESS) {
4282 return;
4283 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004284
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004285 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004286}
4287
4288
4289
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004290
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004291// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004292QCBORError
4293QCBORDecode_GetMIMEInternal(const uint8_t uTagRequirement,
4294 const QCBORItem *pItem,
4295 UsefulBufC *pMessage,
4296 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004297{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004298 const TagSpecification TagSpecText =
4299 {
4300 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004301 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4302 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004303 };
4304 const TagSpecification TagSpecBinary =
4305 {
4306 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004307 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4308 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004309 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004310
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004311 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004312
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004313 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004314 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004315 if(pbIsTag257 != NULL) {
4316 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004317 }
4318 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004319 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004320 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004321 if(pbIsTag257 != NULL) {
4322 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004323 }
4324 uReturn = QCBOR_SUCCESS;
4325
4326 } else {
4327 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4328 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004329
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004330 return uReturn;
4331}
4332
Laurence Lundblade93d89472020-10-03 22:30:50 -07004333// Improvement: add methods for wrapped CBOR, a simple alternate
4334// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004335
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004336
4337
4338
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004339#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004340
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004341typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004342
4343
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004344// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004345static QCBORError
4346Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004347{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004348 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004349
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004350 if(uResult != 0) {
4351 /* This loop will run a maximum of 19 times because
4352 * UINT64_MAX < 10 ^^ 19. More than that will cause
4353 * exit with the overflow error
4354 */
4355 for(; nExponent > 0; nExponent--) {
4356 if(uResult > UINT64_MAX / 10) {
4357 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4358 }
4359 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004360 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004361
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004362 for(; nExponent < 0; nExponent++) {
4363 uResult = uResult / 10;
4364 if(uResult == 0) {
4365 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4366 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004367 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004368 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004369 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004370
4371 *puResult = uResult;
4372
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004373 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004374}
4375
4376
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004377// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004378static QCBORError
4379Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004380{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004381 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004382
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004383 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004384
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004385 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004386 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004387 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004388 */
4389 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004390 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004391 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004392 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004393 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004394 nExponent--;
4395 }
4396
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004397 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004398 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004399 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4400 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004401 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004402 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004403 }
4404
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004405 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004406
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004407 return QCBOR_SUCCESS;
4408}
4409
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004410
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004411/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004412 Compute value with signed mantissa and signed result. Works with
4413 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004414 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004415static inline QCBORError ExponentiateNN(int64_t nMantissa,
4416 int64_t nExponent,
4417 int64_t *pnResult,
4418 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004419{
4420 uint64_t uResult;
4421
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004422 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004423 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004424 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4425
4426 // Do the exponentiation of the positive mantissa
4427 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4428 if(uReturn) {
4429 return uReturn;
4430 }
4431
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004432
Laurence Lundblade983500d2020-05-14 11:49:34 -07004433 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4434 of INT64_MIN. This assumes two's compliment representation where
4435 INT64_MIN is one increment farther from 0 than INT64_MAX.
4436 Trying to write -INT64_MIN doesn't work to get this because the
4437 compiler tries to work with an int64_t which can't represent
4438 -INT64_MIN.
4439 */
4440 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4441
4442 // Error out if too large
4443 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004444 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4445 }
4446
4447 // Casts are safe because of checks above
4448 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4449
4450 return QCBOR_SUCCESS;
4451}
4452
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004453
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004454/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004455 Compute value with signed mantissa and unsigned result. Works with
4456 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004457 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004458static inline QCBORError ExponentitateNU(int64_t nMantissa,
4459 int64_t nExponent,
4460 uint64_t *puResult,
4461 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004462{
4463 if(nMantissa < 0) {
4464 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4465 }
4466
4467 // Cast to unsigned is OK because of check for negative
4468 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4469 // Exponentiation is straight forward
4470 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4471}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004472
4473
4474/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004475 Compute value with signed mantissa and unsigned result. Works with
4476 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004477 */
4478static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4479 int64_t nExponent,
4480 uint64_t *puResult,
4481 fExponentiator pfExp)
4482{
4483 return (*pfExp)(uMantissa, nExponent, puResult);
4484}
4485
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004486#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004487
4488
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004489
4490
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004491
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004492static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004493{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004494 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004495
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004496 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004497 const uint8_t *pByte = BigNum.ptr;
4498 size_t uLen = BigNum.len;
4499 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004500 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004501 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004502 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004503 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004504 }
4505
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004506 *pResult = uResult;
4507 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004508}
4509
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004510
Laurence Lundblade887add82020-05-17 05:50:34 -07004511static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004512{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004513 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004514}
4515
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004516
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004517static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004518{
4519 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004520 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4521 if(uError) {
4522 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004523 }
4524 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4525 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004526 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004527}
4528
4529
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004530static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004531{
4532 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004533 /* The negative integer furthest from zero for a C int64_t is
4534 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4535 negative number in CBOR is computed as -n - 1 where n is the
4536 encoded integer, where n is what is in the variable BigNum. When
4537 converting BigNum to a uint64_t, the maximum value is thus
4538 INT64_MAX, so that when it -n - 1 is applied to it the result will
4539 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004540
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004541 -n - 1 <= INT64_MIN.
4542 -n - 1 <= -INT64_MAX - 1
4543 n <= INT64_MAX.
4544 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004545 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004546 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004547 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004548 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004549
4550 /// Now apply -n - 1. The cast is safe because
4551 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4552 // is the largest positive integer that an int64_t can
4553 // represent. */
4554 *pnResult = -(int64_t)uResult - 1;
4555
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004556 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004557}
4558
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004559
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004560
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004561
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004562
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004563/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004564Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004565
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004566\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567
Laurence Lundblade93d89472020-10-03 22:30:50 -07004568\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4569 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004570
4571\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4572
Laurence Lundblade93d89472020-10-03 22:30:50 -07004573\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4574 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004575*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004576static QCBORError
4577ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004578{
4579 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004580 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004581 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004582#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004583 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004584 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4585 http://www.cplusplus.com/reference/cmath/llround/
4586 */
4587 // Not interested in FE_INEXACT
4588 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004589 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4590 *pnValue = llround(pItem->val.dfnum);
4591 } else {
4592 *pnValue = lroundf(pItem->val.fnum);
4593 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004594 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4595 // llround() shouldn't result in divide by zero, but catch
4596 // it here in case it unexpectedly does. Don't try to
4597 // distinguish between the various exceptions because it seems
4598 // they vary by CPU, compiler and OS.
4599 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004600 }
4601 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004603 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004604#else
4605 return QCBOR_ERR_HW_FLOAT_DISABLED;
4606#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004607 break;
4608
4609 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004610 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004611 *pnValue = pItem->val.int64;
4612 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004613 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004614 }
4615 break;
4616
4617 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004618 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004619 if(pItem->val.uint64 < INT64_MAX) {
4620 *pnValue = pItem->val.int64;
4621 } else {
4622 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4623 }
4624 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004625 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004626 }
4627 break;
4628
4629 default:
4630 return QCBOR_ERR_UNEXPECTED_TYPE;
4631 }
4632 return QCBOR_SUCCESS;
4633}
4634
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004635
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004636void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004637 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004638 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004639 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004640{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004641 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004642 return;
4643 }
4644
Laurence Lundbladee6430642020-03-14 21:15:44 -07004645 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004646 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4647 if(uError) {
4648 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004649 return;
4650 }
4651
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004652 if(pItem) {
4653 *pItem = Item;
4654 }
4655
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004656 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004657}
4658
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004659
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004660void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4661 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004662 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004663 int64_t *pnValue,
4664 QCBORItem *pItem)
4665{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004666 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004667 if(pMe->uLastError != QCBOR_SUCCESS) {
4668 return;
4669 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004670
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004671 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004672}
4673
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004674
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004675void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4676 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004677 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004678 int64_t *pnValue,
4679 QCBORItem *pItem)
4680{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004681 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004682 if(pMe->uLastError != QCBOR_SUCCESS) {
4683 return;
4684 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004685
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004686 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004687}
4688
4689
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690/*
4691 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004692
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004694
Laurence Lundblade93d89472020-10-03 22:30:50 -07004695 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4696 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697
4698 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4699
Laurence Lundblade93d89472020-10-03 22:30:50 -07004700 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4701 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004702 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004703static QCBORError
4704Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004705{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004706 switch(pItem->uDataType) {
4707
4708 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004710 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004711 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004712 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004713 }
4714 break;
4715
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004716 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004717 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004718 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004719 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004721 }
4722 break;
4723
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004724#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004725 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004727 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004728 pItem->val.expAndMantissa.nExponent,
4729 pnValue,
4730 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004731 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004732 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004733 }
4734 break;
4735
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004736 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004738 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004739 pItem->val.expAndMantissa.nExponent,
4740 pnValue,
4741 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004742 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004743 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004744 }
4745 break;
4746
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004747 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004748 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004749 int64_t nMantissa;
4750 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004751 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4752 if(uErr) {
4753 return uErr;
4754 }
4755 return ExponentiateNN(nMantissa,
4756 pItem->val.expAndMantissa.nExponent,
4757 pnValue,
4758 Exponentitate10);
4759 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004760 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004761 }
4762 break;
4763
4764 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004766 int64_t nMantissa;
4767 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004768 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4769 if(uErr) {
4770 return uErr;
4771 }
4772 return ExponentiateNN(nMantissa,
4773 pItem->val.expAndMantissa.nExponent,
4774 pnValue,
4775 Exponentitate10);
4776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004778 }
4779 break;
4780
4781 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004783 int64_t nMantissa;
4784 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004785 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4786 if(uErr) {
4787 return uErr;
4788 }
4789 return ExponentiateNN(nMantissa,
4790 pItem->val.expAndMantissa.nExponent,
4791 pnValue,
4792 Exponentitate2);
4793 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004795 }
4796 break;
4797
4798 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004800 int64_t nMantissa;
4801 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004802 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4803 if(uErr) {
4804 return uErr;
4805 }
4806 return ExponentiateNN(nMantissa,
4807 pItem->val.expAndMantissa.nExponent,
4808 pnValue,
4809 Exponentitate2);
4810 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004812 }
4813 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004814#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004815
Laurence Lundbladee6430642020-03-14 21:15:44 -07004816
Laurence Lundbladec4537442020-04-14 18:53:22 -07004817 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004818 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004819}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820
4821
Laurence Lundbladec4537442020-04-14 18:53:22 -07004822/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004823 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004824 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004825void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004826{
4827 QCBORItem Item;
4828
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004829 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004831 if(pMe->uLastError == QCBOR_SUCCESS) {
4832 // The above conversion succeeded
4833 return;
4834 }
4835
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004836 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004837 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004838 return;
4839 }
4840
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004842}
4843
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844
4845/*
4846Public function, see header qcbor/qcbor_decode.h file
4847*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004848void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4849 int64_t nLabel,
4850 uint32_t uConvertTypes,
4851 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004852{
4853 QCBORItem Item;
4854
Laurence Lundblade93d89472020-10-03 22:30:50 -07004855 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4856 nLabel,
4857 uConvertTypes,
4858 pnValue,
4859 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004860
4861 if(pMe->uLastError == QCBOR_SUCCESS) {
4862 // The above conversion succeeded
4863 return;
4864 }
4865
4866 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4867 // The above conversion failed in a way that code below can't correct
4868 return;
4869 }
4870
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004872}
4873
4874
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004875/*
4876Public function, see header qcbor/qcbor_decode.h file
4877*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004878void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4879 const char *szLabel,
4880 uint32_t uConvertTypes,
4881 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004882{
4883 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004884 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4885 szLabel,
4886 uConvertTypes,
4887 pnValue,
4888 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004889
4890 if(pMe->uLastError == QCBOR_SUCCESS) {
4891 // The above conversion succeeded
4892 return;
4893 }
4894
4895 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4896 // The above conversion failed in a way that code below can't correct
4897 return;
4898 }
4899
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004900 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004901}
4902
4903
Laurence Lundblade93d89472020-10-03 22:30:50 -07004904static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905{
4906 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004907 case QCBOR_TYPE_DOUBLE:
4908 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004909#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004910 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004911 // Can't use llround here because it will not convert values
4912 // greater than INT64_MAX and less than UINT64_MAX that
4913 // need to be converted so it is more complicated.
4914 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4915 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4916 if(isnan(pItem->val.dfnum)) {
4917 return QCBOR_ERR_FLOAT_EXCEPTION;
4918 } else if(pItem->val.dfnum < 0) {
4919 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4920 } else {
4921 double dRounded = round(pItem->val.dfnum);
4922 // See discussion in DecodeDateEpoch() for
4923 // explanation of - 0x7ff
4924 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4925 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4926 }
4927 *puValue = (uint64_t)dRounded;
4928 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004929 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004930 if(isnan(pItem->val.fnum)) {
4931 return QCBOR_ERR_FLOAT_EXCEPTION;
4932 } else if(pItem->val.fnum < 0) {
4933 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4934 } else {
4935 float fRounded = roundf(pItem->val.fnum);
4936 // See discussion in DecodeDateEpoch() for
4937 // explanation of - 0x7ff
4938 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4939 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4940 }
4941 *puValue = (uint64_t)fRounded;
4942 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004943 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004944 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4945 // round() and roundf() shouldn't result in exceptions here, but
4946 // catch them to be robust and thorough. Don't try to
4947 // distinguish between the various exceptions because it seems
4948 // they vary by CPU, compiler and OS.
4949 return QCBOR_ERR_FLOAT_EXCEPTION;
4950 }
4951
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004952 } else {
4953 return QCBOR_ERR_UNEXPECTED_TYPE;
4954 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004955#else
4956 return QCBOR_ERR_HW_FLOAT_DISABLED;
4957#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004958 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004959
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004960 case QCBOR_TYPE_INT64:
4961 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4962 if(pItem->val.int64 >= 0) {
4963 *puValue = (uint64_t)pItem->val.int64;
4964 } else {
4965 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4966 }
4967 } else {
4968 return QCBOR_ERR_UNEXPECTED_TYPE;
4969 }
4970 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004971
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004972 case QCBOR_TYPE_UINT64:
4973 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4974 *puValue = pItem->val.uint64;
4975 } else {
4976 return QCBOR_ERR_UNEXPECTED_TYPE;
4977 }
4978 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004979
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004980 default:
4981 return QCBOR_ERR_UNEXPECTED_TYPE;
4982 }
4983
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004984 return QCBOR_SUCCESS;
4985}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004986
4987
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004988void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004989 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004990 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004991 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004992{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004993 if(pMe->uLastError != QCBOR_SUCCESS) {
4994 return;
4995 }
4996
Laurence Lundbladec4537442020-04-14 18:53:22 -07004997 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004998
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004999 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5000 if(uError) {
5001 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005002 return;
5003 }
5004
Laurence Lundbladea826c502020-05-10 21:07:00 -07005005 if(pItem) {
5006 *pItem = Item;
5007 }
5008
Laurence Lundblade93d89472020-10-03 22:30:50 -07005009 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005010}
5011
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005012
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005013void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005014 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005015 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016 uint64_t *puValue,
5017 QCBORItem *pItem)
5018{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005019 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005020 if(pMe->uLastError != QCBOR_SUCCESS) {
5021 return;
5022 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005023
Laurence Lundblade93d89472020-10-03 22:30:50 -07005024 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005025}
5026
5027
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005028void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005029 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005030 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005031 uint64_t *puValue,
5032 QCBORItem *pItem)
5033{
5034 if(pMe->uLastError != QCBOR_SUCCESS) {
5035 return;
5036 }
5037
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005038 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005039 if(pMe->uLastError != QCBOR_SUCCESS) {
5040 return;
5041 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005042
Laurence Lundblade93d89472020-10-03 22:30:50 -07005043 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005044}
5045
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005046
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005047
Laurence Lundblade93d89472020-10-03 22:30:50 -07005048static QCBORError
5049UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005050{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005051 switch(pItem->uDataType) {
5052
5053 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005054 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005055 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
5056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005058 }
5059 break;
5060
5061 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005062 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005063 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5064 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005065 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005066 }
5067 break;
5068
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005069#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005070
5071 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005072 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005073 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005074 pItem->val.expAndMantissa.nExponent,
5075 puValue,
5076 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005077 } 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_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005083 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005084 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
5085 pItem->val.expAndMantissa.nExponent,
5086 puValue,
5087 Exponentitate2);
5088 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005089 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005090 }
5091 break;
5092
5093 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005094 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005095 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005096 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005097 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005098 if(uErr != QCBOR_SUCCESS) {
5099 return uErr;
5100 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005101 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005102 pItem->val.expAndMantissa.nExponent,
5103 puValue,
5104 Exponentitate10);
5105 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005106 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005107 }
5108 break;
5109
5110 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005111 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005112 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5113 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005114 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005115 }
5116 break;
5117
5118 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005119 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005120 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005121 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005122 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005123 if(uErr != QCBOR_SUCCESS) {
5124 return uErr;
5125 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005126 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005127 pItem->val.expAndMantissa.nExponent,
5128 puValue,
5129 Exponentitate2);
5130 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005131 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005132 }
5133 break;
5134
5135 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005136 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005137 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5138 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005139 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005140 }
5141 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005142#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005143 default:
5144 return QCBOR_ERR_UNEXPECTED_TYPE;
5145 }
5146}
5147
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005148
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005149/*
5150 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005151 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005152void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005153{
5154 QCBORItem Item;
5155
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005156 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005157
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005158 if(pMe->uLastError == QCBOR_SUCCESS) {
5159 // The above conversion succeeded
5160 return;
5161 }
5162
5163 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5164 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005165 return;
5166 }
5167
Laurence Lundblade93d89472020-10-03 22:30:50 -07005168 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005169}
5170
Laurence Lundbladec4537442020-04-14 18:53:22 -07005171
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005172/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005173 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005174*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005175void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005176 int64_t nLabel,
5177 uint32_t uConvertTypes,
5178 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005179{
5180 QCBORItem Item;
5181
Laurence Lundblade93d89472020-10-03 22:30:50 -07005182 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5183 nLabel,
5184 uConvertTypes,
5185 puValue,
5186 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005187
5188 if(pMe->uLastError == QCBOR_SUCCESS) {
5189 // The above conversion succeeded
5190 return;
5191 }
5192
5193 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5194 // The above conversion failed in a way that code below can't correct
5195 return;
5196 }
5197
Laurence Lundblade93d89472020-10-03 22:30:50 -07005198 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005199}
5200
5201
5202/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005203 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005204*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005205void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005206 const char *szLabel,
5207 uint32_t uConvertTypes,
5208 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005209{
5210 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005211 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5212 szLabel,
5213 uConvertTypes,
5214 puValue,
5215 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005216
5217 if(pMe->uLastError == QCBOR_SUCCESS) {
5218 // The above conversion succeeded
5219 return;
5220 }
5221
5222 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5223 // The above conversion failed in a way that code below can't correct
5224 return;
5225 }
5226
Laurence Lundblade93d89472020-10-03 22:30:50 -07005227 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005228}
5229
5230
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005231
5232
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005233#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005234static QCBORError ConvertDouble(const QCBORItem *pItem,
5235 uint32_t uConvertTypes,
5236 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005237{
5238 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005239 case QCBOR_TYPE_FLOAT:
5240#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5241 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5242 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005243 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005244 *pdValue = (double)pItem->val.fnum;
5245 } else {
5246 return QCBOR_ERR_UNEXPECTED_TYPE;
5247 }
5248 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005249#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005250 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005251#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005252 break;
5253
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005254 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005255 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5256 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005257 *pdValue = pItem->val.dfnum;
5258 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005259 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005260 }
5261 }
5262 break;
5263
5264 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005265#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005266 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005267 // A simple cast seems to do the job with no worry of exceptions.
5268 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005269 *pdValue = (double)pItem->val.int64;
5270
5271 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005272 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005273 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005274#else
5275 return QCBOR_ERR_HW_FLOAT_DISABLED;
5276#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005277 break;
5278
5279 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005280#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005281 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005282 // A simple cast seems to do the job with no worry of exceptions.
5283 // There will be precision loss for some values.
5284 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005285 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005286 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005287 }
5288 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005289#else
5290 return QCBOR_ERR_HW_FLOAT_DISABLED;
5291#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005292
5293 default:
5294 return QCBOR_ERR_UNEXPECTED_TYPE;
5295 }
5296
5297 return QCBOR_SUCCESS;
5298}
5299
5300
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005301void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005302 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005303 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005304 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005305{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005306 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005307 return;
5308 }
5309
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005310 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005311
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005312 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005313 if(uError) {
5314 pMe->uLastError = (uint8_t)uError;
5315 return;
5316 }
5317
5318 if(pItem) {
5319 *pItem = Item;
5320 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005321
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005322 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005323}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005324
Laurence Lundbladec4537442020-04-14 18:53:22 -07005325
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005326void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5327 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005328 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005329 double *pdValue,
5330 QCBORItem *pItem)
5331{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005332 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005333 if(pMe->uLastError != QCBOR_SUCCESS) {
5334 return;
5335 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005336
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005337 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005338}
5339
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005340
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005341void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5342 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005343 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005344 double *pdValue,
5345 QCBORItem *pItem)
5346{
5347 if(pMe->uLastError != QCBOR_SUCCESS) {
5348 return;
5349 }
5350
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005351 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005352 if(pMe->uLastError != QCBOR_SUCCESS) {
5353 return;
5354 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005355
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005356 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005357}
5358
5359
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005360#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005361static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5362{
5363 double dResult;
5364
5365 dResult = 0.0;
5366 const uint8_t *pByte = BigNum.ptr;
5367 size_t uLen = BigNum.len;
5368 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005369 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005370 while(uLen--) {
5371 dResult = (dResult * 256.0) + (double)*pByte++;
5372 }
5373
5374 return dResult;
5375}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005376#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5377
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005378
Laurence Lundblade93d89472020-10-03 22:30:50 -07005379static QCBORError
5380DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005381{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005382#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005383 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005384 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5385 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5386 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005387 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005388
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005389#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005390 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005391 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005392 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005393 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5394 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5395 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005396 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005397 }
5398 break;
5399
5400 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005401 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005402 // Underflow gives 0, overflow gives infinity
5403 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5404 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005405 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005406 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005407 }
5408 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005409#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005410
5411 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005412 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005413 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5414 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005415 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005416 }
5417 break;
5418
5419 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005420 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005421 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005422 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005423 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005424 }
5425 break;
5426
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005427#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005428 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005429 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005430 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5431 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5432 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005433 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005434 }
5435 break;
5436
5437 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005438 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005439 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5440 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5441 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005442 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005443 }
5444 break;
5445
5446 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005447 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005448 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5449 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5450 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005451 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005452 }
5453 break;
5454
5455 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005456 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005457 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005458 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5459 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005460 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005461 }
5462 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005463#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005464
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005465 default:
5466 return QCBOR_ERR_UNEXPECTED_TYPE;
5467 }
5468
5469 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005470
5471#else
5472 (void)pItem;
5473 (void)uConvertTypes;
5474 (void)pdValue;
5475 return QCBOR_ERR_HW_FLOAT_DISABLED;
5476#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5477
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005478}
5479
5480
5481/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005482 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005483*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005484void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5485 uint32_t uConvertTypes,
5486 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005487{
5488
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005489 QCBORItem Item;
5490
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005491 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005492
5493 if(pMe->uLastError == QCBOR_SUCCESS) {
5494 // The above conversion succeeded
5495 return;
5496 }
5497
5498 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5499 // The above conversion failed in a way that code below can't correct
5500 return;
5501 }
5502
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005503 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005504}
5505
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005506
5507/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005508 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005509*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005510void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5511 int64_t nLabel,
5512 uint32_t uConvertTypes,
5513 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005514{
5515 QCBORItem Item;
5516
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005517 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005518
5519 if(pMe->uLastError == QCBOR_SUCCESS) {
5520 // The above conversion succeeded
5521 return;
5522 }
5523
5524 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5525 // The above conversion failed in a way that code below can't correct
5526 return;
5527 }
5528
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005529 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005530}
5531
5532
5533/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005534 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005535*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005536void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5537 const char *szLabel,
5538 uint32_t uConvertTypes,
5539 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005540{
5541 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005542 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005543
5544 if(pMe->uLastError == QCBOR_SUCCESS) {
5545 // The above conversion succeeded
5546 return;
5547 }
5548
5549 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5550 // The above conversion failed in a way that code below can't correct
5551 return;
5552 }
5553
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005554 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005555}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005556#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005557
5558
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005559
5560
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005561#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005562static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5563{
5564 while((uInt & 0xff00000000000000UL) == 0) {
5565 uInt = uInt << 8;
5566 };
5567
5568 UsefulOutBuf UOB;
5569
5570 UsefulOutBuf_Init(&UOB, Buffer);
5571
5572 while(uInt) {
5573 const uint64_t xx = uInt & 0xff00000000000000UL;
5574 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5575 uInt = uInt << 8;
5576 (void)xx;
5577 }
5578
5579 return UsefulOutBuf_OutUBuf(&UOB);
5580}
5581
5582
Laurence Lundblade37286c02022-09-03 10:05:02 -07005583/**
5584 * @brief Check and/or complete mantissa and exponent item.
5585 *
5586 * @param[in] pMe The decoder context
5587 * @param[in] TagSpec Expected type(s)
5588 * @param[in,out] pItem See below
5589 *
5590 * This is for decimal fractions and big floats, both of which are a
5591 * mantissa and exponent.
5592 *
5593 * The input item is either a fully decoded decimal faction or big
5594 * float, or a just the decoded first item of a decimal fraction or
5595 * big float.
5596 *
5597 * On output, the item is always a fully decoded decimal fraction or
5598 * big float.
5599 *
5600 * This errors out if the input type does not meet the TagSpec.
5601 */
5602// TODO: document and see tests for the bug that was fixed by this rewrite
5603static QCBORError
5604MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5605 const TagSpecification TagSpec,
5606 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005607{
5608 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005609
Laurence Lundblade37286c02022-09-03 10:05:02 -07005610 /* pItem could either be an auto-decoded mantissa and exponent or
5611 * the opening array of an undecoded mantissa and exponent. This
5612 * check will succeed on either, but doesn't say which it was.
5613 */
5614 uErr = CheckTagRequirement(TagSpec, pItem);
5615 if(uErr != QCBOR_SUCCESS) {
5616 goto Done;
5617 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005618
Laurence Lundblade37286c02022-09-03 10:05:02 -07005619 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
5620 /* The item is an array, which means is is an undecoded mantissa
5621 * and exponent. This call consumes the items in the array and
5622 * results in a decoded mantissa and exponent in pItem. This is
5623 * the case where there was no tag.
5624 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005625 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5626 if(uErr != QCBOR_SUCCESS) {
5627 goto Done;
5628 }
5629
Laurence Lundblade37286c02022-09-03 10:05:02 -07005630 /* The above decode didn't determine whether it is a decimal
5631 * fraction or big num. Which of these two depends on what the
5632 * caller wants it decoded as since there is no tag, so fish the
5633 * type out of the TagSpec. */
5634 pItem->uDataType = MantissaExponentDataType(TagSpec.uTaggedTypes[0], pItem);
5635
5636 /* No need to check the type again. All that we need to know was
5637 * that it decoded correctly as a mantissa and exponent. The
5638 * QCBOR type is set out by what was requested.
5639 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005640 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07005641
5642 /* If the item was not an array and the check passed, then
5643 * it is a fully decoded big float or decimal fraction and
5644 * matches what is requested.
5645 */
5646
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005647Done:
5648 return uErr;
5649}
5650
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005651
Laurence Lundblade37286c02022-09-03 10:05:02 -07005652/* Some notes from the work to disable tags.
5653 *
5654 * The API for big floats and decimal fractions seems good.
5655 * If there's any issue with it it's that the code size to
5656 * implement is a bit large because of the conversion
5657 * to/from int and bignum that is required. There is no API
5658 * that doesn't do the conversion so dead stripping will never
5659 * leave that code out.
5660 *
5661 * The implementation itself seems correct, but not as clean
5662 * and neat as it could be. It could probably be smaller too.
5663 *
5664 * The implementation has three main parts / functions
5665 * - The decoding of the array of two
5666 * - All the tag and type checking for the various API functions
5667 * - Conversion to/from bignum and int
5668 *
5669 * The type checking seems like it wastes the most code for
5670 * what it needs to do.
5671 *
5672 * The inlining for the conversion is probably making the
5673 * overall code base larger.
5674 *
5675 * The tests cases could be organized a lot better and be
5676 * more thorough.
5677 *
5678 * Seems also like there could be more common code in the
5679 * first tier part of the public API. Some functions only
5680 * vary by a TagSpec.
5681 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005682static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005683 TagSpecification TagSpec,
5684 QCBORItem *pItem,
5685 int64_t *pnMantissa,
5686 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005687{
5688 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005689
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005690 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005691 if(uErr != QCBOR_SUCCESS) {
5692 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005693 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005694
Laurence Lundblade9b334962020-08-27 10:55:53 -07005695 switch (pItem->uDataType) {
5696
5697 case QCBOR_TYPE_DECIMAL_FRACTION:
5698 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07005699 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005700 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005701 break;
5702
Laurence Lundblade37286c02022-09-03 10:05:02 -07005703#ifndef QCBOR_DISABLE_TAGS
5704 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005705 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5706 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5707 *pnExponent = pItem->val.expAndMantissa.nExponent;
5708 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5709 break;
5710
5711 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5712 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5713 *pnExponent = pItem->val.expAndMantissa.nExponent;
5714 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5715 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005716#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005717
5718 default:
5719 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5720 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005721
5722 Done:
5723 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005724}
5725
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005726
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005727static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005728 TagSpecification TagSpec,
5729 QCBORItem *pItem,
5730 UsefulBuf BufferForMantissa,
5731 UsefulBufC *pMantissa,
5732 bool *pbIsNegative,
5733 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005734{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005735 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005736
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005737 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005738 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005739 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005740 }
5741
5742 uint64_t uMantissa;
5743
5744 switch (pItem->uDataType) {
5745
5746 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005747 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005748 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5749 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5750 *pbIsNegative = false;
5751 } else {
5752 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5753 *pbIsNegative = true;
5754 }
5755 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5756 *pnExponent = pItem->val.expAndMantissa.nExponent;
5757 break;
5758
Laurence Lundblade37286c02022-09-03 10:05:02 -07005759#ifndef QCBOR_DISABLE_TAGS
5760 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005761 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005762 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005763 *pnExponent = pItem->val.expAndMantissa.nExponent;
5764 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5765 *pbIsNegative = false;
5766 break;
5767
5768 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005769 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005770 *pnExponent = pItem->val.expAndMantissa.nExponent;
5771 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5772 *pbIsNegative = true;
5773 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005774#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005775
5776 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005777 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005778 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005779
5780Done:
5781 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005782}
5783
5784
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005785/*
5786 Public function, see header qcbor/qcbor_decode.h file
5787*/
5788void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5789 uint8_t uTagRequirement,
5790 int64_t *pnMantissa,
5791 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005792{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005793 if(pMe->uLastError != QCBOR_SUCCESS) {
5794 return;
5795 }
5796
5797 QCBORItem Item;
5798 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5799 if(uError) {
5800 pMe->uLastError = (uint8_t)uError;
5801 return;
5802 }
5803
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005804 const TagSpecification TagSpec =
5805 {
5806 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005807 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5808 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5809 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005810 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005811
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005812 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005813}
5814
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005815
5816/*
5817 Public function, see header qcbor/qcbor_decode.h file
5818*/
5819void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005820 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005821 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005822 int64_t *pnMantissa,
5823 int64_t *pnExponent)
5824{
5825 if(pMe->uLastError != QCBOR_SUCCESS) {
5826 return;
5827 }
5828
5829 QCBORItem Item;
5830 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5831
5832 const TagSpecification TagSpec =
5833 {
5834 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005835 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5836 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5837 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005838 };
5839
5840 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5841}
5842
5843
5844/*
5845 Public function, see header qcbor/qcbor_decode.h file
5846*/
5847void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005848 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005849 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005850 int64_t *pnMantissa,
5851 int64_t *pnExponent)
5852{
5853 if(pMe->uLastError != QCBOR_SUCCESS) {
5854 return;
5855 }
5856
5857 QCBORItem Item;
5858 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5859
5860 const TagSpecification TagSpec =
5861 {
5862 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005863 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5864 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5865 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005866 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005867
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005868 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5869}
5870
5871
5872/*
5873 Public function, see header qcbor/qcbor_decode.h file
5874*/
5875void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5876 uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07005877 UsefulBuf MantissaBuffer,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005878 UsefulBufC *pMantissa,
5879 bool *pbMantissaIsNegative,
5880 int64_t *pnExponent)
5881{
5882 if(pMe->uLastError != QCBOR_SUCCESS) {
5883 return;
5884 }
5885
5886 QCBORItem Item;
5887 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5888 if(uError) {
5889 pMe->uLastError = (uint8_t)uError;
5890 return;
5891 }
5892
5893 const TagSpecification TagSpec =
5894 {
5895 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005896 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5897 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5898 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005899 };
5900
Laurence Lundblade93d89472020-10-03 22:30:50 -07005901 ProcessMantissaAndExponentBig(pMe,
5902 TagSpec,
5903 &Item,
5904 MantissaBuffer,
5905 pMantissa,
5906 pbMantissaIsNegative,
5907 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005908}
5909
5910
5911/*
5912 Public function, see header qcbor/qcbor_decode.h file
5913*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005914void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005915 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005916 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005917 UsefulBuf BufferForMantissa,
5918 UsefulBufC *pMantissa,
5919 bool *pbIsNegative,
5920 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005921{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005922 if(pMe->uLastError != QCBOR_SUCCESS) {
5923 return;
5924 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005926 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005927 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005928 if(pMe->uLastError != QCBOR_SUCCESS) {
5929 return;
5930 }
5931
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005932 const TagSpecification TagSpec =
5933 {
5934 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005935 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5936 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5937 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005938 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005939
Laurence Lundblade93d89472020-10-03 22:30:50 -07005940 ProcessMantissaAndExponentBig(pMe,
5941 TagSpec,
5942 &Item,
5943 BufferForMantissa,
5944 pMantissa,
5945 pbIsNegative,
5946 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005947}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005948
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005949
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005950/*
5951 Public function, see header qcbor/qcbor_decode.h file
5952*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005953void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005954 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005955 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005956 UsefulBuf BufferForMantissa,
5957 UsefulBufC *pMantissa,
5958 bool *pbIsNegative,
5959 int64_t *pnExponent)
5960{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005961 if(pMe->uLastError != QCBOR_SUCCESS) {
5962 return;
5963 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005964
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005965 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005966 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5967 if(pMe->uLastError != QCBOR_SUCCESS) {
5968 return;
5969 }
5970
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005971 const TagSpecification TagSpec =
5972 {
5973 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005974 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5975 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5976 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005977 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005978
5979 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5980}
5981
5982
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005983/*
5984 Public function, see header qcbor/qcbor_decode.h file
5985*/
5986void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5987 uint8_t uTagRequirement,
5988 int64_t *pnMantissa,
5989 int64_t *pnExponent)
5990{
5991 if(pMe->uLastError != QCBOR_SUCCESS) {
5992 return;
5993 }
5994
5995 QCBORItem Item;
5996 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5997 if(uError) {
5998 pMe->uLastError = (uint8_t)uError;
5999 return;
6000 }
6001 const TagSpecification TagSpec =
6002 {
6003 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006004 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6005 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6006 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006007 };
6008
6009 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6010}
6011
6012
6013/*
6014 Public function, see header qcbor/qcbor_decode.h file
6015*/
6016void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006017 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006018 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006019 int64_t *pnMantissa,
6020 int64_t *pnExponent)
6021{
6022 if(pMe->uLastError != QCBOR_SUCCESS) {
6023 return;
6024 }
6025
6026 QCBORItem Item;
6027 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6028 if(pMe->uLastError != QCBOR_SUCCESS) {
6029 return;
6030 }
6031
6032 const TagSpecification TagSpec =
6033 {
6034 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006035 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6036 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6037 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006038 };
6039
6040 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6041}
6042
6043
6044/*
6045 Public function, see header qcbor/qcbor_decode.h file
6046*/
6047void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006048 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006049 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006050 int64_t *pnMantissa,
6051 int64_t *pnExponent)
6052{
6053 if(pMe->uLastError != QCBOR_SUCCESS) {
6054 return;
6055 }
6056
6057 QCBORItem Item;
6058 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6059 if(pMe->uLastError != QCBOR_SUCCESS) {
6060 return;
6061 }
6062
6063 const TagSpecification TagSpec =
6064 {
6065 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006066 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6067 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6068 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006069 };
6070
6071 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6072}
6073
6074
6075/*
6076 Public function, see header qcbor/qcbor_decode.h file
6077*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006078void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6079 uint8_t uTagRequirement,
6080 UsefulBuf MantissaBuffer,
6081 UsefulBufC *pMantissa,
6082 bool *pbMantissaIsNegative,
6083 int64_t *pnExponent)
6084{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006085 if(pMe->uLastError != QCBOR_SUCCESS) {
6086 return;
6087 }
6088
6089 QCBORItem Item;
6090 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6091 if(uError) {
6092 pMe->uLastError = (uint8_t)uError;
6093 return;
6094 }
6095
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006096 const TagSpecification TagSpec =
6097 {
6098 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006099 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6100 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6101 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006102 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006103
6104 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006105}
6106
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006107
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006108/*
6109 Public function, see header qcbor/qcbor_decode.h file
6110*/
6111void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006112 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006113 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006114 UsefulBuf BufferForMantissa,
6115 UsefulBufC *pMantissa,
6116 bool *pbIsNegative,
6117 int64_t *pnExponent)
6118{
6119 if(pMe->uLastError != QCBOR_SUCCESS) {
6120 return;
6121 }
6122
6123 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006124 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6125 if(pMe->uLastError != QCBOR_SUCCESS) {
6126 return;
6127 }
6128
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006129 const TagSpecification TagSpec =
6130 {
6131 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006132 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6133 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6134 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006135 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006136
Laurence Lundblade93d89472020-10-03 22:30:50 -07006137 ProcessMantissaAndExponentBig(pMe,
6138 TagSpec,
6139 &Item,
6140 BufferForMantissa,
6141 pMantissa,
6142 pbIsNegative,
6143 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006144}
6145
6146
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006147/*
6148 Public function, see header qcbor/qcbor_decode.h file
6149*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006150void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006151 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006152 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006153 UsefulBuf BufferForMantissa,
6154 UsefulBufC *pMantissa,
6155 bool *pbIsNegative,
6156 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006157{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006158 if(pMe->uLastError != QCBOR_SUCCESS) {
6159 return;
6160 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006161
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006162 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006163 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6164 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006165 return;
6166 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006167
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006168 const TagSpecification TagSpec =
6169 {
6170 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006171 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6172 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6173 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006174 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006175
Laurence Lundblade93d89472020-10-03 22:30:50 -07006176 ProcessMantissaAndExponentBig(pMe,
6177 TagSpec,
6178 &Item,
6179 BufferForMantissa,
6180 pMantissa,
6181 pbIsNegative,
6182 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006183}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006184
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006185#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */