blob: 46c4f126ad3cd078a131f770aaf89f42ff5361bc [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003 Copyright (c) 2018-2022, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080049
Laurence Lundbladea9489f82020-09-12 13:50:56 -070050#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070051
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080053
54
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070055static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070056QCBORItem_IsMapOrArray(const QCBORItem *pMe)
57{
58 const uint8_t uDataType = pMe->uDataType;
59 return uDataType == QCBOR_TYPE_MAP ||
60 uDataType == QCBOR_TYPE_ARRAY ||
61 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
62}
63
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070064static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070065QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
66{
67 if(!QCBORItem_IsMapOrArray(pMe)){
68 return false;
69 }
70
71 if(pMe->val.uCount != 0) {
72 return false;
73 }
74 return true;
75}
76
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070077static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070078QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
79{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080080#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070081 if(!QCBORItem_IsMapOrArray(pMe)){
82 return false;
83 }
84
85 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
86 return false;
87 }
88 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080089#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
90 (void)pMe;
91 return false;
92#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070093}
94
95
Laurence Lundbladeee851742020-01-08 08:37:05 -080096/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070097 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080098 ===========================================================================*/
99
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
102 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700103 */
104
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700106static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700107DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700108{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700109 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800110 /* Limit in DecodeNesting_Descend against more than
111 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700113 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114}
115
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700116
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700117static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700118DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700120 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800121 /* Limit in DecodeNesting_Descend against more than
122 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700124 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700128static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700129DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
131 return pNesting->pCurrentBounded->u.ma.uStartOffset;
132}
133
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700134
Laurence Lundblade085d7952020-07-24 10:26:30 -0700135static inline bool
136DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
137{
138 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700146static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700150 return true;
151 } else {
152 return false;
153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154}
155
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700156
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700157static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159{
160 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800161 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800164
165#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700166 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800167 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700168 return false;
169 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800170
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800171#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
172
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800173 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174 return true;
175}
176
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700177static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700178DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700179{
180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800181 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700188static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
191 return true;
192 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700193 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194 return true;
195 }
196 return false;
197}
198
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700199
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700200static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800202 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700203 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800204 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
205 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
206 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700207 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700209
210 if(bIsEmpty) {
211 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
212 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700216static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700217{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700218 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700222static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224{
225 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800226 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800230 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700233 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800234 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700235 return false;
236 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800237 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800238 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
239 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800240 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700241 return false;
242 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800243 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700244 return true;
245}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700247
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700248static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700249DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800251 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
253 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700254 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700255 return false;
256 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257}
258
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700259
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700260static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
264 return true;
265 } else {
266 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700268}
269
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700270
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700271static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700272DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700273{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700274 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275 return false;
276 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
278 if(pNesting->pCurrentBounded->uLevelType != uType) {
279 return false;
280 }
281
282 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700283}
284
Laurence Lundblade02625d42020-06-25 14:41:41 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700287DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700288{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800289 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700290 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700291}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700292
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700295DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
296{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800297 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700298 pNesting->pCurrent->u.ma.uCountCursor++;
299}
300
301
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700302static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700303DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
304{
305 pNesting->pCurrent--;
306}
307
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308
309static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700310DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800312 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700313 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700314 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 }
316
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800317 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700318 pNesting->pCurrent++;
319
320 pNesting->pCurrent->uLevelType = uType;
321
322 return QCBOR_SUCCESS;
323}
324
325
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700326static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
328 bool bIsEmpty,
329 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700330{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700331 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800332 * Should only be called on map/array.
333 *
334 * Have descended into this before this is called. The job here is
335 * just to mark it in bounded mode.
336 *
337 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
338 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
339 *
340 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700341 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800342 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700343 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700344 }
345
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700346 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700347
348 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349
350 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700351}
352
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700353
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700354static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700355DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 uint8_t uQCBORType,
357 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700359 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360
361 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800362 /* Nothing to do for empty definite-length arrays. They are just are
363 * effectively the same as an item that is not a map or array.
364 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800366 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700367 }
368
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800369 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700370 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
371 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700372 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373 goto Done;
374 }
375
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700376 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800381 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700382 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
383 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384
385 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700386
387Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 return uError;;
389}
390
391
392static inline void
393DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
394{
395 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
396}
397
398
399static inline void
400DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
401{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700402 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700403 pNesting->pCurrentBounded--;
404 if(DecodeNesting_IsCurrentBounded(pNesting)) {
405 break;
406 }
407 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700408}
409
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800410
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700411static inline void
412DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
413{
414 pNesting->pCurrent = pNesting->pCurrentBounded;
415}
416
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700417
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700418static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700420 uint32_t uEndOffset,
421 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700423 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700425 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427 goto Done;
428 }
429
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800430 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700431 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
432 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700433
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800434 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435 pNesting->pCurrentBounded = pNesting->pCurrent;
436
437Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438 return uError;;
439}
440
Laurence Lundbladed0304932020-06-27 10:59:38 -0700441
442static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700443DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444{
445 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446}
447
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700448
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700449static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800450DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
451{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700452 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
453 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
454 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455}
456
457
458static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700460{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700461 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700462 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
463 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700464}
465
466
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700467static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800468DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
469 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700470{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700471 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700472}
473
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800476DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
477 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700478{
479 *pNesting = *pSave;
480}
481
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700482
Laurence Lundblade02625d42020-06-25 14:41:41 -0700483static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700484DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700485{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700486 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487}
488
489
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800490
491
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800492#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800493/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
495
496 The following four functions are pretty wrappers for invocation of
497 the string allocator supplied by the caller.
498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500
Laurence Lundbladeee851742020-01-08 08:37:05 -0800501static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800502StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800503{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800504 /* These pragmas allow the "-Wcast-qual" warnings flag to be set for
505 * gcc and clang. This is the one place where the const needs to be
506 * cast away so const can be use in the rest of the code.
507 */
Dave Thaler93c01182022-08-06 15:08:35 -0400508#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800509#pragma GCC diagnostic push
510#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400511#endif
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800512 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
Dave Thaler93c01182022-08-06 15:08:35 -0400513#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800514#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400515#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800516}
517
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518// StringAllocator_Reallocate called with pMem NULL is
519// equal to StringAllocator_Allocate()
520static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800521StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800522 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800525 /* See comment in StringAllocator_Free() */
Dave Thaler93c01182022-08-06 15:08:35 -0400526#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800527#pragma GCC diagnostic push
528#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400529#endif
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800530 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
Dave Thaler93c01182022-08-06 15:08:35 -0400531#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800532#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400533#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534}
535
Laurence Lundbladeee851742020-01-08 08:37:05 -0800536static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800537StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800538{
539 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
540}
541
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800543StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800545 /* See comment in StringAllocator_Free() */
Dave Thaler93c01182022-08-06 15:08:35 -0400546#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800547#pragma GCC diagnostic push
548#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400549#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800550 if(pMe->pfAllocator) {
551 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
552 }
Dave Thaler93c01182022-08-06 15:08:35 -0400553#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800554#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400555#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800557#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558
559
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800560
561
Laurence Lundbladeee851742020-01-08 08:37:05 -0800562/*===========================================================================
563 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800565 See qcbor/qcbor_decode.h for definition of the object
566 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800569 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800571void QCBORDecode_Init(QCBORDecodeContext *pMe,
572 UsefulBufC EncodedCBOR,
573 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800575 memset(pMe, 0, sizeof(QCBORDecodeContext));
576 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
577 /* Don't bother with error check on decode mode. If a bad value is
578 * passed it will just act as if the default normal mode of 0 was set.
579 */
580 pMe->uDecodeMode = (uint8_t)nDecodeMode;
581 DecodeNesting_Init(&(pMe->nesting));
582
583 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
584 * GetNext_TaggedItem() and MapTagNumber(). */
585 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586}
587
588
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800589#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
590
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800592 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700593 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
595 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800596 void *pAllocateContext,
597 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800599 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
600 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
601 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700602}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800603#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800606
607
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800608/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800609 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800611void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800612 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700613{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800614 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700615 (void)pMe;
616 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700617}
618
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700619
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800620
621
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800623 * Decoding items is done in six layers, one calling the next one
624 * down. If a layer has no work to do for a particular item, it
625 * returns quickly.
626 *
627 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
628 * data items, turning them into the local C representation. For the
629 * most simple it is just associating a QCBOR_TYPE with the data. For
630 * the complex ones that an aggregate of data items, there is some
631 * further decoding and some limited recursion.
632 *
633 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
634 * ends of maps and arrays. It tracks descending into and ascending
635 * out of maps/arrays. It processes breaks that terminate
636 * indefinite-length maps and arrays.
637 *
638 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
639 * items, the label and the data, that make up a map entry. It only
640 * does work on maps. It combines the label and data items into one
641 * labeled item.
642 *
643 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
644 * numbers. It turns the tag numbers into bit flags associated with
645 * the data item. No actual decoding of the contents of the tag is
646 * performed here.
647 *
648 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
649 * that make up an indefinite-length string into one string item. It
650 * uses the string allocator to create contiguous space for the
651 * item. It processes all breaks that are part of indefinite-length
652 * strings.
653 *
654 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
655 * CBOR. Each atomic data item has a "major type", an integer
656 * "argument" and optionally some content. For text and byte strings,
657 * the content is the bytes that make up the string. These are the
658 * smallest data items that are considered to be well-formed. The
659 * content may also be other data items in the case of aggregate
660 * types. They are not handled in this layer.
661 *
662 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
663 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800665
666
667/*
668 * Note about use of int and unsigned variables.
669 *
670 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
671 * used carefully here, and in particular why it isn't used in the
672 * public interface. Also see
673 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
674 *
675 * Int is used for values that need less than 16-bits and would be
676 * subject to integer promotion and result in complaining from static
677 * analyzers.
678 */
679
680
681/**
682 * @brief Decode the CBOR head, the type and argument.
683 *
684 * @param[in] pUInBuf The input buffer to read from.
685 * @param[out] pnMajorType The decoded major type.
686 * @param[out] puArgument The decoded argument.
687 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
688 *
689 * @retval QCBOR_ERR_UNSUPPORTED
690 * @retval QCBOR_ERR_HIT_END
691 *
692 * This decodes the CBOR "head" that every CBOR data item has. See
693 * longer explaination of the head in documentation for
694 * QCBOREncode_EncodeHead().
695 *
696 * This does the network->host byte order conversion. The conversion
697 * here also results in the conversion for floats in addition to that
698 * for lengths, tags and integer values.
699 *
700 * The int type is preferred to uint8_t for some variables as this
701 * avoids integer promotions, can reduce code size and makes static
702 * analyzers happier.
703 */
704static inline QCBORError
705DecodeHead(UsefulInputBuf *pUInBuf,
706 int *pnMajorType,
707 uint64_t *puArgument,
708 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800710 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800711
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800712 /* Get the initial byte that every CBOR data item has and break it
713 * down. */
714 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800715 const int nTmpMajorType = nInitialByte >> 5;
716 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800717
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800718 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800719 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 /* Need to get 1,2,4 or 8 additional argument bytes. Map
723 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
724 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800725 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800728 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800730 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800731 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
732 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800734 /* The reserved and thus-far unused additional info values */
735 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800736 goto Done;
737 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800738 /* Less than 24, additional info is argument or 31, an
739 * indefinite-length. No more bytes to get.
740 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 goto Done;
747 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800748
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800749 /* All successful if arrived here. */
750 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800751 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800752 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800756 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757}
758
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800760/**
761 * @brief Decode integer types, major types 0 and 1.
762 *
763 * @param[in] nMajorType The CBOR major type (0 or 1).
764 * @param[in] uArgument The argument from the head.
765 * @param[out] pDecodedItem The filled in decoded item.
766 *
767 * @retval QCBOR_ERR_INT_OVERFLOW
768 *
769 * Must only be called when major type is 0 or 1.
770 *
771 * CBOR doesn't explicitly specify two's compliment for integers but
772 * all CPUs use it these days and the test vectors in the RFC are
773 * so. All integers in the CBOR structure are positive and the major
774 * type indicates positive or negative. CBOR can express positive
775 * integers up to 2^x - 1 where x is the number of bits and negative
776 * integers down to 2^x. Note that negative numbers can be one more
777 * away from zero than positive. Stdint, as far as I can tell, uses
778 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700779 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700780static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800781DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800783 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800784
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800786 if (uArgument <= INT64_MAX) {
787 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800796 if(uArgument <= INT64_MAX) {
797 /* CBOR's representation of negative numbers lines up with
798 * the two-compliment representation. A negative integer has
799 * one more in range than a positive integer. INT64_MIN is
800 * equal to (-INT64_MAX) - 1.
801 */
802 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800804
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800806 /* C can't represent a negative integer in this range so it
807 * is an error.
808 */
809 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810 }
811 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700814}
815
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800816
817/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
819#error QCBOR_TYPE_FALSE macro value wrong
820#endif
821
822#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
823#error QCBOR_TYPE_TRUE macro value wrong
824#endif
825
826#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
827#error QCBOR_TYPE_NULL macro value wrong
828#endif
829
830#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
831#error QCBOR_TYPE_UNDEF macro value wrong
832#endif
833
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700834#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
835#error QCBOR_TYPE_BREAK macro value wrong
836#endif
837
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
839#error QCBOR_TYPE_DOUBLE macro value wrong
840#endif
841
842#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
843#error QCBOR_TYPE_FLOAT macro value wrong
844#endif
845
Laurence Lundblade9b334962020-08-27 10:55:53 -0700846
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847/**
848 * @brief Decode major type 7 -- true, false, floating-point, break...
849 *
850 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
851 * @param[in] uArgument The argument from the head.
852 * @param[out] pDecodedItem The filled in decoded item.
853 *
854 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200855 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800856 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800859static inline QCBORError
860DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
861{
862 QCBORError uReturn = QCBOR_SUCCESS;
863
864 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
865 * checks above make sure uAdditionalInfo values line up with
866 * uDataType values. DecodeHead() never returns an AdditionalInfo
867 * > 0x1f so cast is safe.
868 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800869 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800871 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
873 * are caught before this is called.
874 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800876 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700877#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800878 /* Half-precision is returned as a double. The cast to
879 * uint16_t is safe because the encoded value was 16 bits. It
880 * was widened to 64 bits to be passed in here.
881 */
882 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700883 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800884#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200885 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700886 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200888#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800889 /* Single precision is normally returned as a double since
890 * double is widely supported, there is no loss of precision,
891 * it makes it easy for the caller in most cases and it can
892 * be converted back to single with no loss of precision
893 *
894 * The cast to uint32_t is safe because the encoded value was
895 * 32 bits. It was widened to 64 bits to be passed in here.
896 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700897 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800898 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700899#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800900 /* In the normal case, use HW to convert float to
901 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700902 pDecodedItem->val.dfnum = (double)f;
903 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800904#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800905 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700906 pDecodedItem->val.fnum = f;
907 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
908
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800909 /* IEEE754_FloatToDouble() could be used here to return as
910 * a double, but it adds object code and most likely
911 * anyone disabling FLOAT HW use doesn't care about floats
912 * and wants to save object code.
913 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800914#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700915 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200916#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
917 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700918 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700919
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800920 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200921#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800922 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700923 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200924#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
925 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700926 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800928 case CBOR_SIMPLEV_FALSE: /* 20 */
929 case CBOR_SIMPLEV_TRUE: /* 21 */
930 case CBOR_SIMPLEV_NULL: /* 22 */
931 case CBOR_SIMPLEV_UNDEF: /* 23 */
932 case CBOR_SIMPLE_BREAK: /* 31 */
933 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
936 if(uArgument <= CBOR_SIMPLE_BREAK) {
937 /* This takes out f8 00 ... f8 1f which should be encoded
938 * as e0 … f7
939 */
940 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 goto Done;
942 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800943 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800945 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800947 /* DecodeHead() will make uArgument equal to
948 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
949 * safe because the 2, 4 and 8 byte lengths of uNumber are in
950 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800952 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953 break;
954 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700956Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800957 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958}
959
960
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800961/**
962 * @brief Decode text and byte strings
963 *
964 * @param[in] pAllocator The string allocator or NULL.
965 * @param[in] uStrLen The length of the string.
966 * @param[in] pUInBuf The surce from which to read the string's bytes.
967 * @param[out] pDecodedItem The filled in decoded item.
968 *
969 * @retval QCBOR_ERR_HIT_END
970 * @retval QCBOR_ERR_STRING_ALLOCATE
971 * @retval QCBOR_ERR_STRING_TOO_LONG
972 *
973 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
974 * pDecodedItem. If @c pAllocator is not NULL then memory for the
975 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800977static inline QCBORError
978DecodeBytes(const QCBORInternalAllocator *pAllocator,
979 uint64_t uStrLen,
980 UsefulInputBuf *pUInBuf,
981 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800985 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
986 * CPUs. This check makes the casts to size_t below safe.
987 *
988 * The max is 4 bytes less than the largest sizeof() so this can be
989 * tested by putting a SIZE_MAX length in the CBOR test input (no
990 * one will care the limit on strings is 4 bytes shorter).
991 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800992 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800994 goto Done;
995 }
996
997 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530998 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800999 /* Failed to get the bytes for this string item */
1000 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301001 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301003
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001004#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005 /* Note that this is not where allocation to coalesce
1006 * indefinite-length strings is done. This is for when the caller
1007 * has requested all strings be allocated. Disabling indefinite
1008 * length strings also disables this allocate-all option.
1009 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001010 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001011 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301013 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001014 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301015 goto Done;
1016 }
1017 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001018 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001019 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301020 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1022 (void)pAllocator;
1023#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1024
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001025 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001026 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301028Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001029 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030}
1031
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001032
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001033/**
1034 * @brief Map the CBOR major types for strings to the QCBOR types.
1035 *
1036 * @param[in] nCBORMajorType The CBOR major type to convert.
1037 * @retturns QCBOR type number.
1038 *
1039 * This only works for the two string types.
1040 */
1041static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001042{
1043 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1044 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1045 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001046
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001047 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1048 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1049 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051 return (uint8_t)(nCBORMajorType + 4);
1052}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053
1054
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001055/**
1056 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1057 *
1058 * @param[in] nCBORMajorType The CBOR major type to convert.
1059 * @retturns QCBOR type number.
1060 *
1061 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001062 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001063static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001065 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1066 #error QCBOR_TYPE_ARRAY value not lined up with major type
1067 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001069 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1070 #error QCBOR_TYPE_MAP value not lined up with major type
1071 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001073 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074}
1075
1076
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001077/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001078 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080 * @param[in] pUInBuf Input buffer to read data item from.
1081 * @param[out] pDecodedItem The filled-in decoded item.
1082 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001083 *
1084 * @retval QCBOR_ERR_UNSUPPORTED
1085 * @retval QCBOR_ERR_HIT_END
1086 * @retval QCBOR_ERR_INT_OVERFLOW
1087 * @retval QCBOR_ERR_STRING_ALLOCATE
1088 * @retval QCBOR_ERR_STRING_TOO_LONG
1089 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001090 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001091 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001092 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1093 *
1094 * This decodes the most primitive / atomic data item. It does
1095 * no combing of data items.
1096 */
1097static QCBORError
1098DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1099 QCBORItem *pDecodedItem,
1100 const QCBORInternalAllocator *pAllocator)
1101{
1102 QCBORError uReturn;
1103
1104 /* Get the major type and the argument. The argument could be
1105 * length of more bytes or the value depending on the major
1106 * type. nAdditionalInfo is an encoding of the length of the
1107 * uNumber and is needed to decode floats and doubles.
1108 */
1109 int nMajorType = 0;
1110 uint64_t uArgument = 0;
1111 int nAdditionalInfo = 0;
1112
1113 memset(pDecodedItem, 0, sizeof(QCBORItem));
1114
1115 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1116 if(uReturn) {
1117 goto Done;
1118 }
1119
1120 /* At this point the major type and the argument are valid. We've
1121 * got the type and the argument that starts every CBOR data item.
1122 */
1123 switch (nMajorType) {
1124 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1125 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1126 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1127 uReturn = QCBOR_ERR_BAD_INT;
1128 } else {
1129 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1130 }
1131 break;
1132
1133 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1134 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1135 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1136 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1137 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1138 } else {
1139 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1140 }
1141 break;
1142
1143 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1144 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1145 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1146 /* Indefinite-length string. */
1147#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1148 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1149#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1150 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1151 break;
1152#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1153 } else {
1154 /* Definite-length string. */
1155 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1156 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1157 goto Done;
1158 }
1159 /* cast OK because of check above */
1160 pDecodedItem->val.uCount = (uint16_t)uArgument;
1161 }
1162 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1163 break;
1164
1165 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1166 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1167 uReturn = QCBOR_ERR_BAD_INT;
1168 } else {
1169 pDecodedItem->val.uTagV = uArgument;
1170 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1171 }
1172 break;
1173
1174 case CBOR_MAJOR_TYPE_SIMPLE:
1175 /* Major type 7: float, double, true, false, null... */
1176 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1177 break;
1178
1179 default:
1180 /* Never happens because DecodeHead() should never return > 7 */
1181 uReturn = QCBOR_ERR_UNSUPPORTED;
1182 break;
1183 }
1184
1185Done:
1186 return uReturn;
1187}
1188
1189
1190/**
1191 * @brief Process indefinite-length strings (decode layer 5).
1192 *
1193 * @param[in] pMe Decoder context
1194 * @param[out] pDecodedItem The decoded item that work is done on.
1195 *
1196 * @retval QCBOR_ERR_UNSUPPORTED
1197 * @retval QCBOR_ERR_HIT_END
1198 * @retval QCBOR_ERR_INT_OVERFLOW
1199 * @retval QCBOR_ERR_STRING_ALLOCATE
1200 * @retval QCBOR_ERR_STRING_TOO_LONG
1201 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001202 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001203 * @retval QCBOR_ERR_BAD_TYPE_7
1204 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001205 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1206 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001208 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001209 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001210 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001211 * If it is, this loops getting the subsequent chunk data items that
1212 * make up the string. The string allocator is used to make a
1213 * contiguous buffer for the chunks. When this completes @c
1214 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001215 *
1216 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001217 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001218static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001219QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001220{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001221 /* Aproximate stack usage
1222 * 64-bit 32-bit
1223 * local vars 32 16
1224 * 2 UsefulBufs 32 16
1225 * QCBORItem 56 52
1226 * TOTAL 120 74
1227 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001228
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001229 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001230 * coalescing the chunks of an indefinite-length string, 2)
1231 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001232 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001233 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001234 * strings cannot be processed at all without a string allocator.
1235 *
1236 * The second used is in DecodeBytes() which is called by
1237 * GetNext_Item() below. This second use unneccessary for most use
1238 * and only happens when requested in the call to
1239 * QCBORDecode_SetMemPool(). If the second use not requested then
1240 * NULL is passed for the string allocator to GetNext_Item().
1241 *
1242 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1243 * allocator altogether and thus both of these uses. It reduced the
1244 * decoder object code by about 400 bytes.
1245 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001246 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001248#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001249 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001250
1251 if(pMe->StringAllocator.pfAllocator) {
1252 pAllocator = &(pMe->StringAllocator);
1253 if(pMe->bStringAllocateAll) {
1254 pAllocatorForGetNext = pAllocator;
1255 }
1256 }
1257#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1258
1259 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001260 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001261 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001262 goto Done;
1263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001264
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001265 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001266 const uint8_t uStringType = pDecodedItem->uDataType;
1267 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001268 goto Done;
1269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001271 /* Is this a string with an indefinite length? */
1272 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1273 goto Done;
1274 }
1275
1276#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001277 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001278 if(pAllocator == NULL) {
1279 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1280 goto Done;
1281 }
1282
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001283 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001284 UsefulBufC FullString = NULLUsefulBufC;
1285
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001286 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001287 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001288 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001289 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001290 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001291 * be allocated. They are always copied in the the contiguous
1292 * buffer allocated here.
1293 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001294 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 if(uReturn) {
1296 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001297 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001298
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001299 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001300 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001301 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001302 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301303 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001304 break;
1305 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001306
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001307 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001308 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001309 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001310 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001311 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001312 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001313 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1314 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001315 break;
1316 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001317
David Navarro9123e5b2022-03-28 16:04:03 +02001318 if (StringChunkItem.val.string.len > 0) {
1319 /* The first time throurgh FullString.ptr is NULL and this is
1320 * equivalent to StringAllocator_Allocate(). Subsequently it is
1321 * not NULL and a reallocation happens.
1322 */
1323 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1324 FullString.ptr,
1325 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001326
David Navarro9123e5b2022-03-28 16:04:03 +02001327 if(UsefulBuf_IsNULL(NewMem)) {
1328 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1329 break;
1330 }
1331
1332 /* Copy new string chunk to the end of accumulated string */
1333 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001334 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001335 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001336
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001337 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1338 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001339 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001340 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001341#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1342 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1343#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001344
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001345Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001346 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001347}
1348
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001349
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001350/**
1351 * @brief This converts a tag number to a shorter mapped value for storage.
1352 *
1353 * @param[in] pMe The decode context.
1354 * @param[in] uUnMappedTag The tag number to map
1355 * @param[out] puMappedTagNumer The stored tag number.
1356 *
1357 * @return error code.
1358 *
1359 * The main point of mapping tag numbers is make QCBORItem
1360 * smaller. With this mapping storage of 4 tags takes up 8
1361 * bytes. Without, it would take up 32 bytes.
1362 *
1363 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1364 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1365 *
1366 * See also UnMapTagNumber() and @ref QCBORItem.
1367 */
1368static inline QCBORError
1369MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1370{
1371 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1372 unsigned uTagMapIndex;
1373 /* Is there room in the tag map, or is it in it already? */
1374 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1375 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1376 break;
1377 }
1378 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1379 break;
1380 }
1381 }
1382 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1383 return QCBOR_ERR_TOO_MANY_TAGS;
1384 }
1385
1386 /* Covers the cases where tag is new and were it is already in the map */
1387 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1388 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1389
1390 } else {
1391 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1392 }
1393
1394 return QCBOR_SUCCESS;
1395}
1396
1397
1398/**
1399 * @brief This converts a mapped tag number to the actual tag number.
1400 *
1401 * @param[in] pMe The decode context.
1402 * @param[in] uMappedTagNumber The stored tag number.
1403 *
1404 * @return The actual tag number is returned or
1405 * @ref CBOR_TAG_INVALID64 on error.
1406 *
1407 * This is the reverse of MapTagNumber()
1408 */
1409static uint64_t
1410UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1411{
1412 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1413 return uMappedTagNumber;
1414 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001415 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001416 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001417 /* This won't be negative because of code below in
1418 * MapTagNumber()
1419 */
1420 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1421 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001422 }
1423}
1424
Laurence Lundblade9b334962020-08-27 10:55:53 -07001425
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001426/**
1427 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1428 *
1429 * @param[in] pMe Decoder context
1430 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001431
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001432 * @retval QCBOR_ERR_UNSUPPORTED
1433 * @retval QCBOR_ERR_HIT_END
1434 * @retval QCBOR_ERR_INT_OVERFLOW
1435 * @retval QCBOR_ERR_STRING_ALLOCATE
1436 * @retval QCBOR_ERR_STRING_TOO_LONG
1437 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001438 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439 * @retval QCBOR_ERR_BAD_TYPE_7
1440 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1441 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1442 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1443 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1444 * @retval QCBOR_ERR_TOO_MANY_TAGS
1445 *
1446 * This loops getting atomic data items until one is not a tag
1447 * number. Usually this is largely pass-through because most
1448 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001449 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001450static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001451QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001452{
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001453 /* Accummulate the tags from multiple items here and then copy them
1454 * into the last item, the non-tag item.
1455 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001456 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1457
1458 /* Initialize to CBOR_TAG_INVALID16 */
1459 #if CBOR_TAG_INVALID16 != 0xffff
1460 /* Be sure the memset does the right thing. */
1461 #err CBOR_TAG_INVALID16 tag not defined as expected
1462 #endif
1463 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001464
Laurence Lundblade9b334962020-08-27 10:55:53 -07001465 QCBORError uReturn = QCBOR_SUCCESS;
1466
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001467 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001468 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001469 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001470 if(uErr != QCBOR_SUCCESS) {
1471 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001472 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001473 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001474
Laurence Lundblade9b334962020-08-27 10:55:53 -07001475 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001476 /* Successful exit from loop; maybe got some tags, maybe not */
1477 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001478 break;
1479 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001480
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001481 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1482 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001483 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001484 /* Continue on to get all tags wrapping this item even though
1485 * it is erroring out in the end. This allows decoding to
1486 * continue. This is a resource limit error, not a problem
1487 * with being well-formed CBOR.
1488 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001489 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001490 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001491 /* Slide tags over one in the array to make room at index 0.
1492 * Must use memmove because the move source and destination
1493 * overlap.
1494 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001495 memmove(&auItemsTags[1],
1496 auItemsTags,
1497 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001498
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001499 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001500 uint16_t uMappedTagNumber = 0;
1501 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001502 /* Continue even on error so as to consume all tags wrapping
1503 * this data item so decoding can go on. If MapTagNumber()
1504 * errors once it will continue to error.
1505 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001506 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001507 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001508
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001509Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001510 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001511}
1512
1513
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001514/**
1515 * @brief Combine a map entry label and value into one item (decode layer 3).
1516 *
1517 * @param[in] pMe Decoder context
1518 * @param[out] pDecodedItem The decoded item that work is done on.
1519 *
1520 * @retval QCBOR_ERR_UNSUPPORTED
1521 * @retval QCBOR_ERR_HIT_END
1522 * @retval QCBOR_ERR_INT_OVERFLOW
1523 * @retval QCBOR_ERR_STRING_ALLOCATE
1524 * @retval QCBOR_ERR_STRING_TOO_LONG
1525 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001526 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001527 * @retval QCBOR_ERR_BAD_TYPE_7
1528 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1529 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1530 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1531 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1532 * @retval QCBOR_ERR_TOO_MANY_TAGS
1533 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1534 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1535 *
1536 * If a the current nesting level is a map, then this
1537 * combines pairs of items into one data item with a label
1538 * and value.
1539 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001540 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001541 * not a map.
1542 *
1543 * This also implements maps-as-array mode where a map
1544 * is treated like an array to allow caller to do their
1545 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001546 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001547static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001548QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001549{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001550 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1551 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001552 goto Done;
1553 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001554
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001555 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1556 /* Break can't be a map entry */
1557 goto Done;
1558 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001559
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001560 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1561 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001562
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001563 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1564 /* Save label in pDecodedItem and get the next which will
1565 * be the real data item.
1566 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001567 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001568 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1569 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001570 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001571 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001572
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301573 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001574
1575 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001576 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001577 pDecodedItem->label.string = LabelItem.val.string;
1578 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001579 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1580 /* It's not a string and we only want strings */
1581 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001582 goto Done;
1583 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1584 pDecodedItem->label.int64 = LabelItem.val.int64;
1585 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1586 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1587 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1588 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1589 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1590 pDecodedItem->label.string = LabelItem.val.string;
1591 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1592 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1593 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594 /* label is not an int or a string. It is an arrray
1595 * or a float or such and this implementation doesn't handle that.
1596 * Also, tags on labels are ignored.
1597 */
1598 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001599 goto Done;
1600 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001601 }
1602 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001603 /* Decoding of maps as arrays to let the caller decide what to do
1604 * about labels, particularly lables that are not integers or
1605 * strings.
1606 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001607 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001608 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001609 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001610 goto Done;
1611 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001612 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001613 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1614 * Cast is needed because of integer promotion.
1615 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001616 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001617 }
1618 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001619
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001620Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001621 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001622}
1623
1624
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001625#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001626/**
1627 * @brief Peek and see if next data item is a break;
1628 *
1629 * @param[in] pUIB UsefulInputBuf to read from.
1630 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1631 *
1632 * @return Any decoding error.
1633 *
1634 * See if next item is a CBOR break. If it is, it is consumed,
1635 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001636*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001637static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001638NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1639{
1640 *pbNextIsBreak = false;
1641 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001642 QCBORItem Peek;
1643 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001644 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001645 if(uReturn != QCBOR_SUCCESS) {
1646 return uReturn;
1647 }
1648 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001649 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001650 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001651 } else {
1652 *pbNextIsBreak = true;
1653 }
1654 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001655
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001656 return QCBOR_SUCCESS;
1657}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001658#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001659
1660
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001661/**
1662 * @brief Ascend up nesting levels if all items in them have been consumed.
1663 *
1664 * @param[in] pMe The decode context.
1665 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1666 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001667 * An item was just consumed, now figure out if it was the
1668 * end of an array/map map that can be closed out. That
1669 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001670*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001671static QCBORError
1672QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001673{
1674 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001675
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001676 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001677 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1678
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1680 /* Nesting level is bstr-wrapped CBOR */
1681
1682 /* Ascent for bstr-wrapped CBOR is always by explicit call
1683 * so no further ascending can happen.
1684 */
1685 break;
1686
1687 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1688 /* Level is a definite-length array/map */
1689
1690 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001691 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1692 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001693 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001694 break;
1695 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001696 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001697 * is time to ascend one level. This happens below.
1698 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001699
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001700#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001701 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001702 /* Level is an indefinite-length array/map. */
1703
1704 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001705 bool bIsBreak = false;
1706 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1707 if(uReturn != QCBOR_SUCCESS) {
1708 goto Done;
1709 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001710
1711 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001712 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001713 break;
1714 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001715
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001716 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001717 * it is time to ascend one level.
1718 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001719
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001720#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001721 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001722
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001723
1724 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001725
Laurence Lundblade93d89472020-10-03 22:30:50 -07001726 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001727 * QCBORDecode_ExitBoundedMode().
1728 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001729 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001730 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001731 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001732 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001733 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001734 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001735
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001736 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001737 break;
1738 }
1739
1740 /* Finally, actually ascend one level. */
1741 DecodeNesting_Ascend(&(pMe->nesting));
1742 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001743
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001744 uReturn = QCBOR_SUCCESS;
1745
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001746#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001747Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001748#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1749
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001750 return uReturn;
1751}
1752
1753
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001754/**
1755 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1756 *
1757 * @param[in] pMe Decoder context
1758 * @param[out] pDecodedItem The decoded item that work is done on.
1759 *
1760 * @retval QCBOR_ERR_UNSUPPORTED
1761 * @retval QCBOR_ERR_HIT_END
1762 * @retval QCBOR_ERR_INT_OVERFLOW
1763 * @retval QCBOR_ERR_STRING_ALLOCATE
1764 * @retval QCBOR_ERR_STRING_TOO_LONG
1765 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001766 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001767 * @retval QCBOR_ERR_BAD_TYPE_7
1768 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1769 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1770 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1771 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1772 * @retval QCBOR_ERR_TOO_MANY_TAGS
1773 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1774 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1775 * @retval QCBOR_ERR_NO_MORE_ITEMS
1776 * @retval QCBOR_ERR_BAD_BREAK
1777 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1778 *
1779 * This handles the traversal descending into and asecnding out of
1780 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1781 * definite- and indefinte-length maps and arrays by looking at the
1782 * item count or finding CBOR breaks. It detects the ends of the
1783 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001784 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001785static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001786QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001787{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001788 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001789 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001790
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001791 /* If out of bytes to consume, it is either the end of the
1792 * top-level sequence of some bstr-wrapped CBOR that was entered.
1793 *
1794 * In the case of bstr-wrapped CBOR, the length of the
1795 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1796 * the bstr-wrapped CBOR is exited, the length is set back to the
1797 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001798 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001799 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001800 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001801 goto Done;
1802 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001803
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001804 /* Check to see if at the end of a bounded definite-length map or
1805 * array. The check for a break ending indefinite-length array is
1806 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001807 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001808 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001809 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001810 goto Done;
1811 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001812
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001813 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001814 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001815 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1816 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001817 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001818 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301819
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001820 /* Breaks ending arrays/maps are processed later in the call to
1821 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001822 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301823 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001824 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301825 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301826 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001827
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001828 /* Record the nesting level for this data item before processing
1829 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001830 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001831 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001832
Laurence Lundblade642282a2020-06-23 12:00:33 -07001833
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001834 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001835 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001836 /* If the new item is a map or array, descend.
1837 *
1838 * Empty indefinite-length maps and arrays are descended into,
1839 * but then ascended out of in the next chunk of code.
1840 *
1841 * Maps and arrays do count as items in the map/array that
1842 * encloses them so a decrement needs to be done for them too,
1843 * but that is done only when all the items in them have been
1844 * processed, not when they are opened with the exception of an
1845 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001846 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001847 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001848 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001849 pDecodedItem->uDataType,
1850 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001851 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001852 /* This error is probably a traversal error and it overrides
1853 * the non-traversal error.
1854 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001855 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001856 goto Done;
1857 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001858 }
1859
Laurence Lundblade02625d42020-06-25 14:41:41 -07001860 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1861 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1862 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001863 /* The following cases are handled here:
1864 * - A non-aggregate item like an integer or string
1865 * - An empty definite-length map or array
1866 * - An indefinite-length map or array that might be empty or might not.
1867 *
1868 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1869 * for an definite-length map/array and break detection for an
1870 * indefinite-0length map/array. If the end of the map/array was
1871 * reached, then it ascends nesting levels, possibly all the way
1872 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001873 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001874 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001875 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001876 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001877 /* This error is probably a traversal error and it overrides
1878 * the non-traversal error.
1879 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001880 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001881 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001882 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301883 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001884
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001885 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001886 /* Tell the caller what level is next. This tells them what
1887 * maps/arrays were closed out and makes it possible for them to
1888 * reconstruct the tree with just the information returned in a
1889 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001890 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001891 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001892 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001893 pDecodedItem->uNextNestLevel = 0;
1894 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001895 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001896 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001898Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001899 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001900}
1901
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001902
1903/**
1904 * @brief Shift 0th tag out of the tag list.
1905 *
1906 * pDecodedItem[in,out] The data item to convert.
1907 *
1908 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1909 * shifted into empty slot at the end of the tag list.
1910 */
1911static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001912{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001913 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1914 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1915 }
1916 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001917}
1918
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001919
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001920/**
1921 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1922 *
1923 * pDecodedItem[in,out] The data item to convert.
1924 *
1925 * @retval QCBOR_ERR_DATE_OVERFLOW
1926 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001927 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001928 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001929 *
1930 * The epoch date tag defined in QCBOR allows for floating-point
1931 * dates. It even allows a protocol to flop between date formats when
1932 * ever it wants. Floating-point dates aren't that useful as they are
1933 * only needed for dates beyond the age of the earth.
1934 *
1935 * This converts all the date formats into one format of an unsigned
1936 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001937 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001938static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001940 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001941
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001942#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001943 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001944#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001945
1946 switch (pDecodedItem->uDataType) {
1947
1948 case QCBOR_TYPE_INT64:
1949 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1950 break;
1951
1952 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001953 /* This only happens for CBOR type 0 > INT64_MAX so it is
1954 * always an overflow.
1955 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001956 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1957 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001958 break;
1959
1960 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001961 case QCBOR_TYPE_FLOAT:
1962#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001963 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001964 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001965 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001966 pDecodedItem->val.dfnum :
1967 (double)pDecodedItem->val.fnum;
1968
1969 /* The conversion from float to integer requires overflow
1970 * detection since floats can be much larger than integers.
1971 * This implementation errors out on these large float values
1972 * since they are beyond the age of the earth.
1973 *
1974 * These constants for the overflow check are computed by the
1975 * compiler. They are not computed at run time.
1976 *
1977 * The factor of 0x7ff is added/subtracted to avoid a
1978 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001979 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001980 * 64-bit integer has 63 bits of precision where a double
1981 * only has 53 bits. Without the 0x7ff factor, the compiler
1982 * may round up and produce a double for the bounds check
1983 * that is larger than can be stored in a 64-bit integer. The
1984 * amount of 0x7ff is picked because it has 11 bits set.
1985 *
1986 * Without the 0x7ff there is a ~30 minute range of time
1987 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001988 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001989 * generate a warning or error without the 0x7ff.
1990 */
1991 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1992 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1993
1994 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001995 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996 goto Done;
1997 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001998
1999 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002000 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002001 pDecodedItem->val.epochDate.fSecondsFraction =
2002 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002004#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002005
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002006 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002007 goto Done;
2008
Laurence Lundblade9682a532020-06-06 18:33:04 -07002009#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002010 break;
2011
2012 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002013 /* It's the arrays and maps that are unrecoverable because
2014 * they are not consumed here. Since this is just an error
2015 * condition, no extra code is added here to make the error
2016 * recoverable for non-arrays and maps like strings. */
2017 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018 goto Done;
2019 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002020
Laurence Lundblade59289e52019-12-30 13:44:37 -08002021 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2022
2023Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002024 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025}
2026
2027
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002028/**
2029 * @brief Convert the days epoch date.
2030 *
2031 * pDecodedItem[in,out] The data item to convert.
2032 *
2033 * @retval QCBOR_ERR_DATE_OVERFLOW
2034 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002035 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002036 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002037 *
2038 * This is much simpler than the other epoch date format because
2039 * floating-porint is not allowed. This is mostly a simple type check.
2040 */
2041static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2042{
2043 QCBORError uReturn = QCBOR_SUCCESS;
2044
2045 switch (pDecodedItem->uDataType) {
2046
2047 case QCBOR_TYPE_INT64:
2048 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2049 break;
2050
2051 case QCBOR_TYPE_UINT64:
2052 /* This only happens for CBOR type 0 > INT64_MAX so it is
2053 * always an overflow.
2054 */
2055 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2056 goto Done;
2057 break;
2058
2059 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002060 /* It's the arrays and maps that are unrecoverable because
2061 * they are not consumed here. Since this is just an error
2062 * condition, no extra code is added here to make the error
2063 * recoverable for non-arrays and maps like strings. */
2064 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002065 goto Done;
2066 break;
2067 }
2068
2069 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2070
2071Done:
2072 return uReturn;
2073}
2074
2075
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002076#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002077/**
2078 * @brief Decode decimal fractions and big floats.
2079 *
2080 * @param[in] pMe The decode context.
2081 * @param[in,out] pDecodedItem On input the array data item that
2082 * holds the mantissa and exponent. On
2083 * output the decoded mantissa and
2084 * exponent.
2085 *
2086 * @returns Decoding errors from getting primitive data items or
2087 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2088 *
2089 * When called pDecodedItem must be the array that is tagged as a big
2090 * float or decimal fraction, the array that has the two members, the
2091 * exponent and mantissa.
2092 *
2093 * This will fetch and decode the exponent and mantissa and put the
2094 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002096static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002097QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002098{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002099 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002101 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002103 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002104 goto Done;
2105 }
2106
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002107 /* A check for pDecodedItem->val.uCount == 2 would work for
2108 * definite-length arrays, but not for indefnite. Instead remember
2109 * the nesting level the two integers must be at, which is one
2110 * deeper than that of the array.
2111 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002112 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2113
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002114 /* --- Which is it, decimal fraction or a bigfloat? --- */
2115 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002116 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2117
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002118 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002119 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002120 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2121 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 goto Done;
2123 }
2124 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002125 /* Array is empty or a map/array encountered when expecting an int */
2126 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002127 goto Done;
2128 }
2129 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002130 /* Data arriving as an unsigned int < INT64_MAX has been
2131 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2132 * also means that the only data arriving here of type
2133 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2134 * and thus an error that will get handled in the next else.
2135 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002136 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2137 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002138 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2139 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002140 goto Done;
2141 }
2142
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002143 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002144 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002145 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2146 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002147 goto Done;
2148 }
2149 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002150 /* Mantissa missing or map/array encountered when expecting number */
2151 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002152 goto Done;
2153 }
2154 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002155 /* Data arriving as an unsigned int < INT64_MAX has been
2156 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2157 * also means that the only data arriving here of type
2158 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2159 * and thus an error that will get handled in an else below.
2160 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002162 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2163 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002164 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002165 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002166 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002167 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2168 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2169 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002171 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2172 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002173 goto Done;
2174 }
2175
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002176 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002177 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002178 /* Extra items in the decimal fraction / big float */
2179 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002180 goto Done;
2181 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002182 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002183
2184Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002185 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002186}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002187#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002188
2189
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002190#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002191/**
2192 * @brief Decode the MIME type tag
2193 *
2194 * @param[in,out] pDecodedItem The item to decode.
2195 *
2196 * Handle the text and binary MIME type tags. Slightly too complicated
2197 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2198 * incorreclty text-only.
2199 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002200static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002201{
2202 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2203 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002204 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002205 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2206 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002207 /* It's the arrays and maps that are unrecoverable because
2208 * they are not consumed here. Since this is just an error
2209 * condition, no extra code is added here to make the error
2210 * recoverable for non-arrays and maps like strings. */
2211 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002212 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002213
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002214 return QCBOR_SUCCESS;
2215}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002216#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002217
2218
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002219/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002220 * Table of CBOR tags whose content is either a text string or a byte
2221 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2222 * of uQCBORtype indicates the content should be a byte string rather
2223 * than a text string
2224 */
2225struct StringTagMapEntry {
2226 uint16_t uTagNumber;
2227 uint8_t uQCBORtype;
2228};
2229
2230#define IS_BYTE_STRING_BIT 0x80
2231#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2232
2233static const struct StringTagMapEntry StringTagMap[] = {
2234 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002235 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002236 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2237 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2238 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2239 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002240#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002241 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2242 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2243 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2244 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002245#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002246 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2247 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2248};
2249
2250
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002251/**
2252 * @brief Process standard CBOR tags whose content is a string
2253 *
2254 * @param[in] uTag The tag.
2255 * @param[in,out] pDecodedItem The data item.
2256 *
2257 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2258 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002259 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002260 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002261 * Process the CBOR tags that whose content is a byte string or a text
2262 * string and for which the string is just passed on to the caller.
2263 *
2264 * This maps the CBOR tag to the QCBOR type and checks the content
2265 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002266 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002267 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002268 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002269static inline QCBORError
2270ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002271{
Laurence Lundblade99615302020-11-29 11:19:47 -08002272 /* This only works on tags that were not mapped; no need for other yet */
2273 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2274 return QCBOR_ERR_UNSUPPORTED;
2275 }
2276
2277 unsigned uIndex;
2278 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2279 if(StringTagMap[uIndex].uTagNumber == uTag) {
2280 break;
2281 }
2282 }
2283
2284 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2285 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002286 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002287 return QCBOR_ERR_UNSUPPORTED;
2288 }
2289
2290 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2291 if(uQCBORType & IS_BYTE_STRING_BIT) {
2292 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2293 }
2294
2295 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002296 /* It's the arrays and maps that are unrecoverable because
2297 * they are not consumed here. Since this is just an error
2298 * condition, no extra code is added here to make the error
2299 * recoverable for non-arrays and maps like strings. */
2300 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002301 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002302
Laurence Lundblade99615302020-11-29 11:19:47 -08002303 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002304 return QCBOR_SUCCESS;
2305}
2306
2307
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002308/**
2309 * @brief Decode tag content for select tags (decoding layer 1).
2310 *
2311 * @param[in] pMe The decode context.
2312 * @param[out] pDecodedItem The decoded item.
2313 *
2314 * @return Decoding error code.
2315 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002316 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2317 * but the whole tag was not decoded. Here, the whole tags (tag number
2318 * and tag content) that are supported by QCBOR are decoded. This is a
2319 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002320 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002321static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002322QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002323{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002324 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002325
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002326 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002327 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002328 goto Done;
2329 }
2330
Laurence Lundblade99615302020-11-29 11:19:47 -08002331 /* When there are no tag numbers for the item, this exits first
2332 * thing and effectively does nothing.
2333 *
2334 * This loops over all the tag numbers accumulated for this item
2335 * trying to decode and interpret them. This stops at the end of
2336 * the list or at the first tag number that can't be interpreted by
2337 * this code. This is effectively a recursive processing of the
2338 * tags number list that handles nested tags.
2339 */
2340 while(1) {
2341 /* Don't bother to unmap tags via QCBORITem.uTags since this
2342 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2343 */
2344 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002345
Laurence Lundblade99615302020-11-29 11:19:47 -08002346 if(uTagToProcess == CBOR_TAG_INVALID16) {
2347 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002348 break;
2349
Laurence Lundblade99615302020-11-29 11:19:47 -08002350 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002351 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002352
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002353 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2354 uReturn = DecodeDaysEpoch(pDecodedItem);
2355
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002356#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002357 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2358 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002359 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002360#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002361#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002362 } else if(uTagToProcess == CBOR_TAG_MIME ||
2363 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002364 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002365#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002366
Laurence Lundblade99615302020-11-29 11:19:47 -08002367 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002368 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002369 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002370
Laurence Lundblade99615302020-11-29 11:19:47 -08002371 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002372 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002373 * an unknown tag. This is the exit from the loop on the
2374 * first unknown tag. It is a successful exit.
2375 */
2376 uReturn = QCBOR_SUCCESS;
2377 break;
2378 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002379 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002380
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002381 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002382 /* Error exit from the loop */
2383 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002384 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002385
2386 /* A tag was successfully processed, shift it out of the list of
2387 * tags returned. This is the loop increment.
2388 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002389 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002390 }
2391
2392Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002393 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002394}
2395
2396
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002397/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002398 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002399 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002400QCBORError
2401QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2402{
2403 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002404 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002405 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002406 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2407 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2408 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002409 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002410}
2411
2412
2413/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002414 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002415 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002416QCBORError
2417QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2418{
2419 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2420 const UsefulInputBuf Save = pMe->InBuf;
2421
2422 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2423
2424 pMe->nesting = SaveNesting;
2425 pMe->InBuf = Save;
2426
2427 return uErr;
2428}
2429
2430
2431/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002432 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002433 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002434void
2435QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2436{
2437 if(pMe->uLastError != QCBOR_SUCCESS) {
2438 return;
2439 }
2440
2441 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2442}
2443
2444
2445/*
2446 * Public function, see header qcbor/qcbor_decode.h file
2447 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002448void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2449{
2450 if(pMe->uLastError != QCBOR_SUCCESS) {
2451 return;
2452 }
2453
2454 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2455}
2456
2457
2458/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002459 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002460 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002461QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002462QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2463 QCBORItem *pDecodedItem,
2464 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002465{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002466 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002467
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002468 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2469 if(uReturn != QCBOR_SUCCESS) {
2470 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002471 }
2472
2473 if(pTags != NULL) {
2474 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002475 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002476 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2477 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002478 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002479 }
2480 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2481 return QCBOR_ERR_TOO_MANY_TAGS;
2482 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002483 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002484 pTags->uNumUsed++;
2485 }
2486 }
2487
2488 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002489}
2490
2491
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002492/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002493 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302494 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002495bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002496 const QCBORItem *pItem,
2497 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002498{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002499 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2500 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002501 break;
2502 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002503 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002504 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002505 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002506 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002507
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002508 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002509}
2510
2511
2512/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002513 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002514 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002515QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002516{
Laurence Lundblade87495732021-02-26 10:05:55 -07002517 if(puConsumed != NULL) {
2518 *puConsumed = pMe->InBuf.cursor;
2519 }
2520
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002521 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002522
2523 if(uReturn != QCBOR_SUCCESS) {
2524 goto Done;
2525 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002526
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002527 /* Error out if all the maps/arrays are not closed out */
2528 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002529 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002530 goto Done;
2531 }
2532
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002533 /* Error out if not all the bytes are consumed */
2534 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002535 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002536 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002537
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002538Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002539 return uReturn;
2540}
2541
2542
2543/*
2544 * Public function, see header qcbor/qcbor_decode.h file
2545 */
2546QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2547{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002548#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002549 /* Call the destructor for the string allocator if there is one.
2550 * Always called, even if there are errors; always have to clean up.
2551 */
2552 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002553#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002554
Laurence Lundblade87495732021-02-26 10:05:55 -07002555 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002556}
2557
2558
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002559/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002560 * Public function, see header qcbor/qcbor_decode.h file
2561 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002562// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002563uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2564 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002565 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002566{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002567 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2568 return CBOR_TAG_INVALID64;
2569 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002570 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2571 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002572 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002573 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002574 }
2575}
2576
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002577
Laurence Lundblade9b334962020-08-27 10:55:53 -07002578/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002579 * Public function, see header qcbor/qcbor_decode.h file
2580 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002581uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2582 uint32_t uIndex)
2583{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002584 if(pMe->uLastError != QCBOR_SUCCESS) {
2585 return CBOR_TAG_INVALID64;
2586 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002587 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2588 return CBOR_TAG_INVALID64;
2589 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002590 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002591 }
2592}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002593
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002594
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002595
2596
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002597#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002598
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002599/* ===========================================================================
2600 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002601
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002602 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002603 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2604 implements the function type QCBORStringAllocate and allows easy
2605 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002606
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002607 This particular allocator is built-in for convenience. The caller
2608 can implement their own. All of this following code will get
2609 dead-stripped if QCBORDecode_SetMemPool() is not called.
2610
2611 This is a very primitive memory allocator. It does not track
2612 individual allocations, only a high-water mark. A free or
2613 reallocation must be of the last chunk allocated.
2614
2615 The size of the pool and offset to free memory are packed into the
2616 first 8 bytes of the memory pool so we don't have to keep them in
2617 the decode context. Since the address of the pool may not be
2618 aligned, they have to be packed and unpacked as if they were
2619 serialized data of the wire or such.
2620
2621 The sizes packed in are uint32_t to be the same on all CPU types
2622 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002623 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002624
2625
Laurence Lundbladeee851742020-01-08 08:37:05 -08002626static inline int
2627MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002628{
2629 // Use of UsefulInputBuf is overkill, but it is convenient.
2630 UsefulInputBuf UIB;
2631
Laurence Lundbladeee851742020-01-08 08:37:05 -08002632 // Just assume the size here. It was checked during SetUp so
2633 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002634 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002635 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2636 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2637 return UsefulInputBuf_GetError(&UIB);
2638}
2639
2640
Laurence Lundbladeee851742020-01-08 08:37:05 -08002641static inline int
2642MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002643{
2644 // Use of UsefulOutBuf is overkill, but convenient. The
2645 // length check performed here is useful.
2646 UsefulOutBuf UOB;
2647
2648 UsefulOutBuf_Init(&UOB, Pool);
2649 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2650 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2651 return UsefulOutBuf_GetError(&UOB);
2652}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002653
2654
2655/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002656 Internal function for an allocation, reallocation free and destuct.
2657
2658 Having only one function rather than one each per mode saves space in
2659 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002660
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002661 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2662 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002663static UsefulBuf
2664MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002665{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002666 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002667
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002668 uint32_t uPoolSize;
2669 uint32_t uFreeOffset;
2670
2671 if(uNewSize > UINT32_MAX) {
2672 // This allocator is only good up to 4GB. This check should
2673 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2674 goto Done;
2675 }
2676 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2677
2678 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2679 goto Done;
2680 }
2681
2682 if(uNewSize) {
2683 if(pMem) {
2684 // REALLOCATION MODE
2685 // Calculate pointer to the end of the memory pool. It is
2686 // assumed that pPool + uPoolSize won't wrap around by
2687 // assuming the caller won't pass a pool buffer in that is
2688 // not in legitimate memory space.
2689 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2690
2691 // Check that the pointer for reallocation is in the range of the
2692 // pool. This also makes sure that pointer math further down
2693 // doesn't wrap under or over.
2694 if(pMem >= pPool && pMem < pPoolEnd) {
2695 // Offset to start of chunk for reallocation. This won't
2696 // wrap under because of check that pMem >= pPool. Cast
2697 // is safe because the pool is always less than UINT32_MAX
2698 // because of check in QCBORDecode_SetMemPool().
2699 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2700
2701 // Check to see if the allocation will fit. uPoolSize -
2702 // uMemOffset will not wrap under because of check that
2703 // pMem is in the range of the uPoolSize by check above.
2704 if(uNewSize <= uPoolSize - uMemOffset) {
2705 ReturnValue.ptr = pMem;
2706 ReturnValue.len = uNewSize;
2707
2708 // Addition won't wrap around over because uNewSize was
2709 // checked to be sure it is less than the pool size.
2710 uFreeOffset = uMemOffset + uNewSize32;
2711 }
2712 }
2713 } else {
2714 // ALLOCATION MODE
2715 // uPoolSize - uFreeOffset will not underflow because this
2716 // pool implementation makes sure uFreeOffset is always
2717 // smaller than uPoolSize through this check here and
2718 // reallocation case.
2719 if(uNewSize <= uPoolSize - uFreeOffset) {
2720 ReturnValue.len = uNewSize;
2721 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002722 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002723 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002724 }
2725 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002726 if(pMem) {
2727 // FREE MODE
2728 // Cast is safe because of limit on pool size in
2729 // QCBORDecode_SetMemPool()
2730 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2731 } else {
2732 // DESTRUCT MODE
2733 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002734 }
2735 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002736
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002737 UsefulBuf Pool = {pPool, uPoolSize};
2738 MemPool_Pack(Pool, uFreeOffset);
2739
2740Done:
2741 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002742}
2743
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002744
Laurence Lundbladef6531662018-12-04 10:42:22 +09002745/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002746 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002747 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002748QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2749 UsefulBuf Pool,
2750 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002751{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002752 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002753 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002754 // constant in the header is correct. This check should optimize
2755 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002756#ifdef _MSC_VER
2757#pragma warning(push)
2758#pragma warning(disable:4127) // conditional expression is constant
2759#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002760 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002761 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002762 }
Dave Thaler93c01182022-08-06 15:08:35 -04002763#ifdef _MSC_VER
2764#pragma warning(pop)
2765#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002766
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002767 // The pool size and free offset packed in to the beginning of pool
2768 // memory are only 32-bits. This check will optimize out on 32-bit
2769 // machines.
2770 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002771 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002772 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002773
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002774 // This checks that the pool buffer given is big enough.
2775 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002776 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002777 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002778
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002779 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002780
Laurence Lundblade30816f22018-11-10 13:40:22 +07002781 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002782}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002783#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002784
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002785
2786
Laurence Lundblade9b334962020-08-27 10:55:53 -07002787static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2788{
2789 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2790}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002791
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002792
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002793/**
2794 * @brief Consume an entire map or array including its contents.
2795 *
2796 * @param[in] pMe The decoder context.
2797 * @param[in] pItemToConsume The array/map whose contents are to be
2798 * consumed.
2799 * @param[out] puNextNestLevel The next nesting level after the item was
2800 * fully consumed.
2801 *
2802 * This may be called when @c pItemToConsume is not an array or
2803 * map. In that case, this is just a pass through for @c puNextNestLevel
2804 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002805 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002806static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807ConsumeItem(QCBORDecodeContext *pMe,
2808 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002809 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002810{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002811 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002812 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002813
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002814 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002815 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2816
2817 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2818 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002819
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002820 /* This works for definite- and indefinite-length maps and
2821 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002822 */
2823 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002824 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002825 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2826 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002827 goto Done;
2828 }
2829 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002830
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002831 *puNextNestLevel = Item.uNextNestLevel;
2832
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002833 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002834
Laurence Lundblade1341c592020-04-11 14:19:05 -07002835 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002836 /* pItemToConsume is not a map or array. Just pass the nesting
2837 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002838 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2839
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002840 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002841 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002842
2843Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002844 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002845}
2846
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002847
2848void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2849{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002850 QCBORDecode_VGetNext(pMe, pDecodedItem);
2851
2852 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002853 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2854 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002855 }
2856}
2857
2858
2859
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002860/* Call only on maps and arrays. Rewinds the cursor
2861 * to the start as if it was just entered.
2862 */
2863static void RewindMapOrArray(QCBORDecodeContext *pMe)
2864{
2865 /* Reset nesting tracking to the deepest bounded level */
2866 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2867
2868 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2869
2870 /* Reposition traversal cursor to the start of the map/array */
2871 UsefulInputBuf_Seek(&(pMe->InBuf),
2872 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2873}
2874
2875
2876/*
2877 Public function, see header qcbor/qcbor_decode.h file
2878 */
2879void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2880{
2881 if(pMe->nesting.pCurrentBounded != NULL) {
2882 /* In a bounded map, array or bstr-wrapped CBOR */
2883
2884 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2885 /* In bstr-wrapped CBOR. */
2886
2887 /* Reposition traversal cursor to start of wrapping byte string */
2888 UsefulInputBuf_Seek(&(pMe->InBuf),
2889 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2890 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2891
2892 } else {
2893 /* In a map or array */
2894 RewindMapOrArray(pMe);
2895 }
2896
2897 } else {
2898 /* Not in anything bounded */
2899
2900 /* Reposition traversal cursor to the start of input CBOR */
2901 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2902
2903 /* Reset nesting tracking to beginning of input. */
2904 DecodeNesting_Init(&(pMe->nesting));
2905 }
2906
2907 pMe->uLastError = QCBOR_SUCCESS;
2908}
2909
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002910
Laurence Lundblade1341c592020-04-11 14:19:05 -07002911/* Return true if the labels in Item1 and Item2 are the same.
2912 Works only for integer and string labels. Returns false
2913 for any other type. */
2914static inline bool
2915MatchLabel(QCBORItem Item1, QCBORItem Item2)
2916{
2917 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2918 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2919 return true;
2920 }
2921 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002922 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002923 return true;
2924 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002925 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002926 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2927 return true;
2928 }
2929 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2930 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2931 return true;
2932 }
2933 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002934
Laurence Lundblade1341c592020-04-11 14:19:05 -07002935 /* Other label types are never matched */
2936 return false;
2937}
2938
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002939
2940/*
2941 Returns true if Item1 and Item2 are the same type
2942 or if either are of QCBOR_TYPE_ANY.
2943 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002944static inline bool
2945MatchType(QCBORItem Item1, QCBORItem Item2)
2946{
2947 if(Item1.uDataType == Item2.uDataType) {
2948 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002949 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002950 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002951 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002952 return true;
2953 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002954 return false;
2955}
2956
2957
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002958/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002959 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002960
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002961 @param[in] pMe The decode context to search.
2962 @param[in,out] pItemArray The items to search for and the items found.
2963 @param[out] puOffset Byte offset of last item matched.
2964 @param[in] pCBContext Context for the not-found item call back.
2965 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002966
2967 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2968
Laurence Lundblade93d89472020-10-03 22:30:50 -07002969 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2970 were found for one of the labels being
2971 search for. This duplicate detection is
2972 only performed for items in pItemArray,
2973 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002974
Laurence Lundblade93d89472020-10-03 22:30:50 -07002975 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2976 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002977
2978 @retval Also errors returned by QCBORDecode_GetNext().
2979
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002980 On input pItemArray contains a list of labels and data types
2981 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002982
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002983 On output the fully retrieved items are filled in with
2984 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002985
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002986 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002987
2988 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002989 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002990static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002991MapSearch(QCBORDecodeContext *pMe,
2992 QCBORItem *pItemArray,
2993 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002994 void *pCBContext,
2995 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002996{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002997 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002998 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002999
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003000 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003001 uReturn = pMe->uLastError;
3002 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003003 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003004
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003005 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003006 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3007 /* QCBOR_TYPE_NONE as first item indicates just looking
3008 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003009 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3010 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003011 }
3012
Laurence Lundblade085d7952020-07-24 10:26:30 -07003013 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3014 // It is an empty bounded array or map
3015 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3016 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003017 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003018 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003019 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003020 // Nothing is ever found in an empty array or map. All items
3021 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003022 uReturn = QCBOR_SUCCESS;
3023 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003024 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003025 }
3026
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003027 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003028 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3029
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003030 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003031 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003032
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003033 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003034 Loop over all the items in the map or array. Each item
3035 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003036 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003037 length maps and arrays. The only reason this is ever
3038 called on arrays is to find their end position.
3039
3040 This will always run over all items in order to do
3041 duplicate detection.
3042
3043 This will exit with failure if it encounters an
3044 unrecoverable error, but continue on for recoverable
3045 errors.
3046
3047 If a recoverable error occurs on a matched item, then
3048 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003049 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003050 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003051 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003052 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003053 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003054 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003055
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003056 /* Get the item */
3057 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003058 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003059 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003060 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003061 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003062 goto Done;
3063 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003064 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003065 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003066 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003067 goto Done;
3068 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003069
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003070 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003071 bool bMatched = false;
3072 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3073 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003074 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003075 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3076 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003077 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003078 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003079 if(uResult != QCBOR_SUCCESS) {
3080 /* The label matches, but the data item is in error */
3081 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003082 goto Done;
3083 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003084 if(!MatchType(Item, pItemArray[nIndex])) {
3085 /* The data item is not of the type(s) requested */
3086 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003087 goto Done;
3088 }
3089
Laurence Lundblade1341c592020-04-11 14:19:05 -07003090 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003091 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003092 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003093 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003094 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003095 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003096 bMatched = true;
3097 }
3098 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003099
3100
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003101 if(!bMatched && pfCallback != NULL) {
3102 /*
3103 Call the callback on unmatched labels.
3104 (It is tempting to do duplicate detection here, but that would
3105 require dynamic memory allocation because the number of labels
3106 that might be encountered is unbounded.)
3107 */
3108 uReturn = (*pfCallback)(pCBContext, &Item);
3109 if(uReturn != QCBOR_SUCCESS) {
3110 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003111 }
3112 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003113
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003114 /*
3115 Consume the item whether matched or not. This
3116 does the work of traversing maps and array and
3117 everything in them. In this loop only the
3118 items at the current nesting level are examined
3119 to match the labels.
3120 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003121 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003122 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003123 goto Done;
3124 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003125
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003126 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003127
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003128 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003129
3130 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003131
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003132 // Check here makes sure that this won't accidentally be
3133 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003134 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003135 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3136 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003137 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3138 goto Done;
3139 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003140 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3141 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003142
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003143 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003144 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3145
3146 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003147 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003148 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003149 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003150 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3151 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003152 }
3153 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003154
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003155 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003156}
3157
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003158
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003159/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003160 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003161*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003162void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3163 int64_t nLabel,
3164 uint8_t uQcborType,
3165 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003166{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003167 if(pMe->uLastError != QCBOR_SUCCESS) {
3168 return;
3169 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003170
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003171 QCBORItem OneItemSeach[2];
3172 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3173 OneItemSeach[0].label.int64 = nLabel;
3174 OneItemSeach[0].uDataType = uQcborType;
3175 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003176
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003177 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003178
3179 *pItem = OneItemSeach[0];
3180
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003181 if(uReturn != QCBOR_SUCCESS) {
3182 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003183 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003184 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003185 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003186 }
3187
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003188 Done:
3189 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003190}
3191
3192
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003193/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003194 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003195*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003196void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3197 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003198 uint8_t uQcborType,
3199 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003200{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003201 if(pMe->uLastError != QCBOR_SUCCESS) {
3202 return;
3203 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003204
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003205 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003206 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3207 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3208 OneItemSeach[0].uDataType = uQcborType;
3209 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003210
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003211 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3212 if(uReturn != QCBOR_SUCCESS) {
3213 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003214 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003215 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003216 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003217 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003218 }
3219
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003220 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003221
3222Done:
3223 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003224}
3225
3226
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003227
Laurence Lundblade93d89472020-10-03 22:30:50 -07003228static QCBORError
3229CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003230{
3231 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3232 if(uDataType == puTypeList[i]) {
3233 return QCBOR_SUCCESS;
3234 }
3235 }
3236 return QCBOR_ERR_UNEXPECTED_TYPE;
3237}
3238
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003239
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003240/**
3241 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003242 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003243
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003244 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3245 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003246
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003247 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3248 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003249 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003250static QCBORError
3251CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003252{
3253 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3254 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3255 /* There are tags that QCBOR couldn't process on this item and
3256 the caller has told us there should not be. */
3257 return QCBOR_ERR_UNEXPECTED_TYPE;
3258 }
3259
3260 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3261 const int nItemType = pItem->uDataType;
3262
3263 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3264 // Must match the tag and only the tag
3265 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3266 }
3267
3268 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3269 if(uReturn == QCBOR_SUCCESS) {
3270 return QCBOR_SUCCESS;
3271 }
3272
3273 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3274 /* Must match the content type and only the content type.
3275 There was no match just above so it is a fail. */
3276 return QCBOR_ERR_UNEXPECTED_TYPE;
3277 }
3278
3279 /* If here it can match either the tag or the content
3280 and it hasn't matched the content, so the end
3281 result is whether it matches the tag. This is
3282 also the case that the CBOR standard discourages. */
3283
3284 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3285}
3286
Laurence Lundblade9b334962020-08-27 10:55:53 -07003287
Laurence Lundblade9b334962020-08-27 10:55:53 -07003288
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003289// This could be semi-private if need be
3290static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003291void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3292 int64_t nLabel,
3293 TagSpecification TagSpec,
3294 QCBORItem *pItem)
3295{
3296 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3297 if(pMe->uLastError != QCBOR_SUCCESS) {
3298 return;
3299 }
3300
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003301 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003302}
3303
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003304
3305// This could be semi-private if need be
3306static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003307void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3308 const char *szLabel,
3309 TagSpecification TagSpec,
3310 QCBORItem *pItem)
3311{
3312 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3313 if(pMe->uLastError != QCBOR_SUCCESS) {
3314 return;
3315 }
3316
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003317 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003318}
3319
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003320// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003321void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3322 int64_t nLabel,
3323 TagSpecification TagSpec,
3324 UsefulBufC *pString)
3325{
3326 QCBORItem Item;
3327 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3328 if(pMe->uLastError == QCBOR_SUCCESS) {
3329 *pString = Item.val.string;
3330 }
3331}
3332
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003333// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003334void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3335 const char * szLabel,
3336 TagSpecification TagSpec,
3337 UsefulBufC *pString)
3338{
3339 QCBORItem Item;
3340 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3341 if(pMe->uLastError == QCBOR_SUCCESS) {
3342 *pString = Item.val.string;
3343 }
3344}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003345
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003346/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003347 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003348*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003349void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003350{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003351 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3352 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003353}
3354
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003355/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003356 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003357*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003358void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3359 QCBORItem *pItemList,
3360 void *pCallbackCtx,
3361 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003362{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003363 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3364 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003365}
3366
3367
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003368/**
3369 * @brief Search for a map/array by label and enter it
3370 *
3371 * @param[in] pMe The decode context.
3372 * @param[in] pSearch The map/array to search for.
3373 *
3374 * @c pSearch is expected to contain one item of type map or array
3375 * with the label specified. The current bounded map will be searched for
3376 * this and if found will be entered.
3377 *
3378 * If the label is not found, or the item found is not a map or array,
3379 * the error state is set.
3380 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003381static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003382{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003383 // The first item in pSearch is the one that is to be
3384 // entered. It should be the only one filled in. Any other
3385 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003386 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003387 return;
3388 }
3389
3390 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003391 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003392 if(pMe->uLastError != QCBOR_SUCCESS) {
3393 return;
3394 }
3395
Laurence Lundblade9b334962020-08-27 10:55:53 -07003396 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003397 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003398 return;
3399 }
3400
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003401
3402 /* The map or array was found. Now enter it.
3403 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003404 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3405 * next item for the pre-order traversal cursor to be the map/array
3406 * found by MapSearch(). The next few lines of code force the
3407 * cursor to that.
3408 *
3409 * There is no need to retain the old cursor because
3410 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3411 * beginning of the map/array being entered.
3412 *
3413 * The cursor is forced by: 1) setting the input buffer position to
3414 * the item offset found by MapSearch(), 2) setting the map/array
3415 * counter to the total in the map/array, 3) setting the nesting
3416 * level. Setting the map/array counter to the total is not
3417 * strictly correct, but this is OK because this cursor only needs
3418 * to be used to get one item and MapSearch() has already found it
3419 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003420 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003421 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003422
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003423 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3424
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003425 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003426
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003427 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003428}
3429
3430
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003431/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003432 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003433*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003434void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003435{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003436 QCBORItem OneItemSeach[2];
3437 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3438 OneItemSeach[0].label.int64 = nLabel;
3439 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3440 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003441
Laurence Lundblade9b334962020-08-27 10:55:53 -07003442 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003443 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003444}
3445
3446
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003447/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003448 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003449*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003450void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003451{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003452 QCBORItem OneItemSeach[2];
3453 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3454 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3455 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3456 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003457
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003458 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003459}
3460
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003461/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003462 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003463*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003464void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003465{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003466 QCBORItem OneItemSeach[2];
3467 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3468 OneItemSeach[0].label.int64 = nLabel;
3469 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3470 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003471
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003472 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003473}
3474
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003475/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003476 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003477*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003478void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3479{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003480 QCBORItem OneItemSeach[2];
3481 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3482 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3483 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3484 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003485
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003486 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003487}
3488
3489
Laurence Lundblade02625d42020-06-25 14:41:41 -07003490// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003491void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003492{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003493 QCBORError uErr;
3494
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003495 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003496 if(pMe->uLastError != QCBOR_SUCCESS) {
3497 // Already in error state; do nothing.
3498 return;
3499 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003500
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003501 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003502 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003503 uErr = QCBORDecode_GetNext(pMe, &Item);
3504 if(uErr != QCBOR_SUCCESS) {
3505 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003506 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003507 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003508 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3509 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003510 }
3511
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003512 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003513
3514
Laurence Lundbladef0499502020-08-01 11:55:57 -07003515 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003516 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003517 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3518 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003519 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003520 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3521 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003522 // Special case to increment nesting level for zero-length maps
3523 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003524 DecodeNesting_Descend(&(pMe->nesting), uType);
3525 }
3526
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003527 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003528
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003529 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3530 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003531
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003532 if(pItem != NULL) {
3533 *pItem = Item;
3534 }
3535
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003536Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003537 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003538}
3539
Laurence Lundblade02625d42020-06-25 14:41:41 -07003540
3541/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003542 This is the common work for exiting a level that is a bounded map,
3543 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003544
3545 One chunk of work is to set up the pre-order traversal so it is at
3546 the item just after the bounded map, array or bstr that is being
3547 exited. This is somewhat complex.
3548
3549 The other work is to level-up the bounded mode to next higest bounded
3550 mode or the top level if there isn't one.
3551 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003552static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003553ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003554{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003555 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003556
Laurence Lundblade02625d42020-06-25 14:41:41 -07003557 /*
3558 First the pre-order-traversal byte offset is positioned to the
3559 item just after the bounded mode item that was just consumed.
3560 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003561 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3562
Laurence Lundblade02625d42020-06-25 14:41:41 -07003563 /*
3564 Next, set the current nesting level to one above the bounded level
3565 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003566
Laurence Lundblade02625d42020-06-25 14:41:41 -07003567 DecodeNesting_CheckBoundedType() is always called before this and
3568 makes sure pCurrentBounded is valid.
3569 */
3570 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3571
3572 /*
3573 This does the complex work of leveling up the pre-order traversal
3574 when the end of a map or array or another bounded level is
3575 reached. It may do nothing, or ascend all the way to the top
3576 level.
3577 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003578 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003579 if(uErr != QCBOR_SUCCESS) {
3580 goto Done;
3581 }
3582
Laurence Lundblade02625d42020-06-25 14:41:41 -07003583 /*
3584 This makes the next highest bounded level the current bounded
3585 level. If there is no next highest level, then no bounded mode is
3586 in effect.
3587 */
3588 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003589
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003590 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003591
3592Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003593 return uErr;
3594}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003595
Laurence Lundblade02625d42020-06-25 14:41:41 -07003596
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003597// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003598void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003599{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003600 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003601 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003602 return;
3603 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003604
Laurence Lundblade02625d42020-06-25 14:41:41 -07003605 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003606
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003607 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003608 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003609 goto Done;
3610 }
3611
Laurence Lundblade02625d42020-06-25 14:41:41 -07003612 /*
3613 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003614 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003615 from previous map search, then do a dummy search.
3616 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003617 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003618 QCBORItem Dummy;
3619 Dummy.uLabelType = QCBOR_TYPE_NONE;
3620 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3621 if(uErr != QCBOR_SUCCESS) {
3622 goto Done;
3623 }
3624 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003625
Laurence Lundblade02625d42020-06-25 14:41:41 -07003626 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003627
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003628Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003629 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003630}
3631
3632
Laurence Lundblade1341c592020-04-11 14:19:05 -07003633
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003634static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003635 const QCBORItem *pItem,
3636 uint8_t uTagRequirement,
3637 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003638{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003639 if(pBstr) {
3640 *pBstr = NULLUsefulBufC;
3641 }
3642
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003643 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003644 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003645 return pMe->uLastError;
3646 }
3647
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003648 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003649
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003650 const TagSpecification TagSpec =
3651 {
3652 uTagRequirement,
3653 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3654 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3655 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003656
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003657 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003658 if(uError != QCBOR_SUCCESS) {
3659 goto Done;
3660 }
3661
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003662 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003663 /* Reverse the decrement done by GetNext() for the bstr so the
3664 * increment in QCBORDecode_NestLevelAscender() called by
3665 * ExitBoundedLevel() will work right.
3666 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003667 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003668 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003669
3670 if(pBstr) {
3671 *pBstr = pItem->val.string;
3672 }
3673
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003674 /* This saves the current length of the UsefulInputBuf and then
3675 * narrows the UsefulInputBuf to start and length of the wrapped
3676 * CBOR that is being entered.
3677 *
3678 * Most of these calls are simple inline accessors so this doesn't
3679 * amount to much code.
3680 */
3681
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003682 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003683 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3684 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003685 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003686 goto Done;
3687 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003688
3689 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3690 pItem->val.string.ptr);
3691 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3692 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3693 /* This should never happen because pItem->val.string.ptr should
3694 * always be valid since it was just returned.
3695 */
3696 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3697 goto Done;
3698 }
3699
3700 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3701
3702 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003703 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003704
Laurence Lundblade02625d42020-06-25 14:41:41 -07003705 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003706 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003707 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003708Done:
3709 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003710}
3711
3712
Laurence Lundblade02625d42020-06-25 14:41:41 -07003713/*
3714 Public function, see header qcbor/qcbor_decode.h file
3715 */
3716void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003717 uint8_t uTagRequirement,
3718 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003719{
3720 if(pMe->uLastError != QCBOR_SUCCESS) {
3721 // Already in error state; do nothing.
3722 return;
3723 }
3724
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003725 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003726 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003727 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3728 if(pMe->uLastError != QCBOR_SUCCESS) {
3729 return;
3730 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003731
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003732 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003733 &Item,
3734 uTagRequirement,
3735 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003736}
3737
3738
Laurence Lundblade02625d42020-06-25 14:41:41 -07003739/*
3740 Public function, see header qcbor/qcbor_decode.h file
3741 */
3742void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003743 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003744 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003745 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003746{
3747 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003748 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003749
Laurence Lundblade93d89472020-10-03 22:30:50 -07003750 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3751 &Item,
3752 uTagRequirement,
3753 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003754}
3755
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003756
Laurence Lundblade02625d42020-06-25 14:41:41 -07003757/*
3758 Public function, see header qcbor/qcbor_decode.h file
3759 */
3760void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003761 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003762 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003763 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003764{
3765 QCBORItem Item;
3766 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3767
Laurence Lundblade93d89472020-10-03 22:30:50 -07003768 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3769 &Item,
3770 uTagRequirement,
3771 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003772}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003773
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003774
Laurence Lundblade02625d42020-06-25 14:41:41 -07003775/*
3776 Public function, see header qcbor/qcbor_decode.h file
3777 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003778void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003779{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003780 if(pMe->uLastError != QCBOR_SUCCESS) {
3781 // Already in error state; do nothing.
3782 return;
3783 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003784
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003785 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003786 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003787 return;
3788 }
3789
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003790 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3791
Laurence Lundblade02625d42020-06-25 14:41:41 -07003792 /*
3793 Reset the length of the UsefulInputBuf to what it was before
3794 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003795 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003796 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003797 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003798
3799
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003800 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003801 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003802}
3803
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003804
Laurence Lundbladee6430642020-03-14 21:15:44 -07003805
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003806
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003807static inline void
3808ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003809{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003810 if(pMe->uLastError != QCBOR_SUCCESS) {
3811 /* Already in error state, do nothing */
3812 return;
3813 }
3814
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003815 switch(pItem->uDataType) {
3816 case QCBOR_TYPE_TRUE:
3817 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003818 break;
3819
3820 case QCBOR_TYPE_FALSE:
3821 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003822 break;
3823
3824 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003825 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003826 break;
3827 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003828 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003829}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003830
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003831
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003832/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003833 * Public function, see header qcbor/qcbor_decode.h file
3834 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003835void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003836{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003837 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003838 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003839 return;
3840 }
3841
Laurence Lundbladec4537442020-04-14 18:53:22 -07003842 QCBORItem Item;
3843
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003844 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3845
3846 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847}
3848
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003849
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003850/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003851 * Public function, see header qcbor/qcbor_decode.h file
3852 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003853void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003854{
3855 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003856 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003858 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003859}
3860
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003861
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003862/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003863 * Public function, see header qcbor/qcbor_decode.h file
3864 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003865void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3866{
3867 QCBORItem Item;
3868 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3869
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003870 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003871}
3872
3873
3874
Laurence Lundbladec7114722020-08-13 05:11:40 -07003875
3876static void ProcessEpochDate(QCBORDecodeContext *pMe,
3877 QCBORItem *pItem,
3878 uint8_t uTagRequirement,
3879 int64_t *pnTime)
3880{
3881 if(pMe->uLastError != QCBOR_SUCCESS) {
3882 // Already in error state, do nothing
3883 return;
3884 }
3885
3886 QCBORError uErr;
3887
3888 const TagSpecification TagSpec =
3889 {
3890 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003891 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3892 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003893 };
3894
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003895 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003896 if(uErr != QCBOR_SUCCESS) {
3897 goto Done;
3898 }
3899
3900 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3901 uErr = DecodeDateEpoch(pItem);
3902 if(uErr != QCBOR_SUCCESS) {
3903 goto Done;
3904 }
3905 }
3906
Laurence Lundblade9b334962020-08-27 10:55:53 -07003907 // Save the tags in the last item's tags in the decode context
3908 // for QCBORDecode_GetNthTagOfLast()
3909 CopyTags(pMe, pItem);
3910
Laurence Lundbladec7114722020-08-13 05:11:40 -07003911 *pnTime = pItem->val.epochDate.nSeconds;
3912
3913Done:
3914 pMe->uLastError = (uint8_t)uErr;
3915}
3916
3917
3918void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003919 uint8_t uTagRequirement,
3920 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003921{
3922 if(pMe->uLastError != QCBOR_SUCCESS) {
3923 // Already in error state, do nothing
3924 return;
3925 }
3926
3927 QCBORItem Item;
3928 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3929
3930 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3931}
3932
3933
3934void
3935QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3936 int64_t nLabel,
3937 uint8_t uTagRequirement,
3938 int64_t *pnTime)
3939{
3940 QCBORItem Item;
3941 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3942 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3943}
3944
3945
3946void
3947QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3948 const char *szLabel,
3949 uint8_t uTagRequirement,
3950 int64_t *pnTime)
3951{
3952 QCBORItem Item;
3953 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3954 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3955}
3956
3957
3958
Laurence Lundblade46d63e92021-05-13 11:37:10 -07003959/*
3960 * Common processing for the RFC 8943 day-count tag. Mostly
3961 * make sure the tag content is correct and copy forward any
3962 * further other tag numbers.
3963 */
3964static void ProcessEpochDays(QCBORDecodeContext *pMe,
3965 QCBORItem *pItem,
3966 uint8_t uTagRequirement,
3967 int64_t *pnDays)
3968{
3969 if(pMe->uLastError != QCBOR_SUCCESS) {
3970 /* Already in error state, do nothing */
3971 return;
3972 }
3973
3974 QCBORError uErr;
3975
3976 const TagSpecification TagSpec =
3977 {
3978 uTagRequirement,
3979 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3980 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3981 };
3982
3983 uErr = CheckTagRequirement(TagSpec, pItem);
3984 if(uErr != QCBOR_SUCCESS) {
3985 goto Done;
3986 }
3987
3988 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
3989 uErr = DecodeDaysEpoch(pItem);
3990 if(uErr != QCBOR_SUCCESS) {
3991 goto Done;
3992 }
3993 }
3994
3995 /* Save the tags in the last item's tags in the decode context
3996 * for QCBORDecode_GetNthTagOfLast()
3997 */
3998 CopyTags(pMe, pItem);
3999
4000 *pnDays = pItem->val.epochDays;
4001
4002Done:
4003 pMe->uLastError = (uint8_t)uErr;
4004}
4005
4006
4007/*
4008 * Public function, see header qcbor/qcbor_decode.h
4009 */
4010void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4011 uint8_t uTagRequirement,
4012 int64_t *pnDays)
4013{
4014 if(pMe->uLastError != QCBOR_SUCCESS) {
4015 /* Already in error state, do nothing */
4016 return;
4017 }
4018
4019 QCBORItem Item;
4020 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4021
4022 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4023}
4024
4025
4026/*
4027 * Public function, see header qcbor/qcbor_decode.h
4028 */
4029void
4030QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4031 int64_t nLabel,
4032 uint8_t uTagRequirement,
4033 int64_t *pnDays)
4034{
4035 QCBORItem Item;
4036 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4037 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4038}
4039
4040
4041/*
4042 * Public function, see header qcbor/qcbor_decode.h
4043 */
4044void
4045QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4046 const char *szLabel,
4047 uint8_t uTagRequirement,
4048 int64_t *pnDays)
4049{
4050 QCBORItem Item;
4051 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4052 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4053}
4054
4055
4056
Laurence Lundbladec7114722020-08-13 05:11:40 -07004057
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004058void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4059 TagSpecification TagSpec,
4060 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004061{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004062 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004063 // Already in error state, do nothing
4064 return;
4065 }
4066
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004067 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004068 QCBORItem Item;
4069
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004070 uError = QCBORDecode_GetNext(pMe, &Item);
4071 if(uError != QCBOR_SUCCESS) {
4072 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004073 return;
4074 }
4075
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004076 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077
4078 if(pMe->uLastError == QCBOR_SUCCESS) {
4079 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004080 } else {
4081 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004082 }
4083}
4084
Laurence Lundbladec4537442020-04-14 18:53:22 -07004085
4086
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004088static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004089 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004090 UsefulBufC *pValue,
4091 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004092{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004093 const TagSpecification TagSpec =
4094 {
4095 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004096 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4097 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004098 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004099
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004100 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004101 if(uErr != QCBOR_SUCCESS) {
4102 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004104
4105 *pValue = pItem->val.string;
4106
4107 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4108 *pbIsNegative = false;
4109 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4110 *pbIsNegative = true;
4111 }
4112
4113 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004114}
4115
4116
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004117/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004118 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004119 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004120void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4121 uint8_t uTagRequirement,
4122 UsefulBufC *pValue,
4123 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004124{
4125 if(pMe->uLastError != QCBOR_SUCCESS) {
4126 // Already in error state, do nothing
4127 return;
4128 }
4129
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004130 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4132 if(uError != QCBOR_SUCCESS) {
4133 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004134 return;
4135 }
4136
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004137 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004138}
4139
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004140
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004141/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004142 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004143*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004144void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4145 int64_t nLabel,
4146 uint8_t uTagRequirement,
4147 UsefulBufC *pValue,
4148 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004149{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 QCBORItem Item;
4151 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004152 if(pMe->uLastError != QCBOR_SUCCESS) {
4153 return;
4154 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004155
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004156 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004157}
4158
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004159
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004160/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004161 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004162*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004163void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4164 const char *szLabel,
4165 uint8_t uTagRequirement,
4166 UsefulBufC *pValue,
4167 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004168{
4169 QCBORItem Item;
4170 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004171 if(pMe->uLastError != QCBOR_SUCCESS) {
4172 return;
4173 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004174
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004175 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004176}
4177
4178
4179
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004180
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004181// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004182QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
4183 const QCBORItem *pItem,
4184 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07004185 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004186{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004187 const TagSpecification TagSpecText =
4188 {
4189 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004190 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4191 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004192 };
4193 const TagSpecification TagSpecBinary =
4194 {
4195 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004196 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4197 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004198 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004199
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004200 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004201
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004202 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004203 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004204 if(pbIsTag257 != NULL) {
4205 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004206 }
4207 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004208 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004209 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004210 if(pbIsTag257 != NULL) {
4211 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004212 }
4213 uReturn = QCBOR_SUCCESS;
4214
4215 } else {
4216 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4217 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004218
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004219 return uReturn;
4220}
4221
Laurence Lundblade93d89472020-10-03 22:30:50 -07004222// Improvement: add methods for wrapped CBOR, a simple alternate
4223// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004224
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004225
4226
4227
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004228#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004229
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004230typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004231
4232
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004233// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004234static QCBORError
4235Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004236{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004237 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004238
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004239 if(uResult != 0) {
4240 /* This loop will run a maximum of 19 times because
4241 * UINT64_MAX < 10 ^^ 19. More than that will cause
4242 * exit with the overflow error
4243 */
4244 for(; nExponent > 0; nExponent--) {
4245 if(uResult > UINT64_MAX / 10) {
4246 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4247 }
4248 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004249 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004250
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004251 for(; nExponent < 0; nExponent++) {
4252 uResult = uResult / 10;
4253 if(uResult == 0) {
4254 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4255 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004256 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004257 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004258 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004259
4260 *puResult = uResult;
4261
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004262 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004263}
4264
4265
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004266// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004267static QCBORError
4268Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004269{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004270 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004271
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004272 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004273
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004274 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004275 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004276 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004277 */
4278 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004279 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004280 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004281 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004282 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004283 nExponent--;
4284 }
4285
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004286 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004287 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004288 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4289 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004290 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004291 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004292 }
4293
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004294 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004295
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004296 return QCBOR_SUCCESS;
4297}
4298
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004299
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004300/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004301 Compute value with signed mantissa and signed result. Works with
4302 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004303 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004304static inline QCBORError ExponentiateNN(int64_t nMantissa,
4305 int64_t nExponent,
4306 int64_t *pnResult,
4307 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004308{
4309 uint64_t uResult;
4310
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004311 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004312 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004313 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4314
4315 // Do the exponentiation of the positive mantissa
4316 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4317 if(uReturn) {
4318 return uReturn;
4319 }
4320
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004321
Laurence Lundblade983500d2020-05-14 11:49:34 -07004322 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4323 of INT64_MIN. This assumes two's compliment representation where
4324 INT64_MIN is one increment farther from 0 than INT64_MAX.
4325 Trying to write -INT64_MIN doesn't work to get this because the
4326 compiler tries to work with an int64_t which can't represent
4327 -INT64_MIN.
4328 */
4329 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4330
4331 // Error out if too large
4332 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004333 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4334 }
4335
4336 // Casts are safe because of checks above
4337 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4338
4339 return QCBOR_SUCCESS;
4340}
4341
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004342
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004343/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004344 Compute value with signed mantissa and unsigned result. Works with
4345 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004346 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004347static inline QCBORError ExponentitateNU(int64_t nMantissa,
4348 int64_t nExponent,
4349 uint64_t *puResult,
4350 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004351{
4352 if(nMantissa < 0) {
4353 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4354 }
4355
4356 // Cast to unsigned is OK because of check for negative
4357 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4358 // Exponentiation is straight forward
4359 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4360}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004361
4362
4363/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004364 Compute value with signed mantissa and unsigned result. Works with
4365 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004366 */
4367static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4368 int64_t nExponent,
4369 uint64_t *puResult,
4370 fExponentiator pfExp)
4371{
4372 return (*pfExp)(uMantissa, nExponent, puResult);
4373}
4374
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004375#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004376
4377
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004378
4379
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004380
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004381static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004382{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004383 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004384
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004385 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004386 const uint8_t *pByte = BigNum.ptr;
4387 size_t uLen = BigNum.len;
4388 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004389 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004390 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004391 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004392 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004393 }
4394
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004395 *pResult = uResult;
4396 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004397}
4398
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004399
Laurence Lundblade887add82020-05-17 05:50:34 -07004400static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004401{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004402 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004403}
4404
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004405
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004406static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004407{
4408 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004409 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4410 if(uError) {
4411 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004412 }
4413 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4414 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004415 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004416}
4417
4418
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004419static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004420{
4421 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004422 /* The negative integer furthest from zero for a C int64_t is
4423 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4424 negative number in CBOR is computed as -n - 1 where n is the
4425 encoded integer, where n is what is in the variable BigNum. When
4426 converting BigNum to a uint64_t, the maximum value is thus
4427 INT64_MAX, so that when it -n - 1 is applied to it the result will
4428 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004429
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004430 -n - 1 <= INT64_MIN.
4431 -n - 1 <= -INT64_MAX - 1
4432 n <= INT64_MAX.
4433 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004434 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004435 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004436 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004437 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004438
4439 /// Now apply -n - 1. The cast is safe because
4440 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4441 // is the largest positive integer that an int64_t can
4442 // represent. */
4443 *pnResult = -(int64_t)uResult - 1;
4444
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004445 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004446}
4447
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004448
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004449
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004450
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004451
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004453Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004456
Laurence Lundblade93d89472020-10-03 22:30:50 -07004457\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4458 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459
4460\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4461
Laurence Lundblade93d89472020-10-03 22:30:50 -07004462\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4463 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004464*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004465static QCBORError
4466ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004467{
4468 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004469 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004470 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004471#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004473 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4474 http://www.cplusplus.com/reference/cmath/llround/
4475 */
4476 // Not interested in FE_INEXACT
4477 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004478 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4479 *pnValue = llround(pItem->val.dfnum);
4480 } else {
4481 *pnValue = lroundf(pItem->val.fnum);
4482 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004483 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4484 // llround() shouldn't result in divide by zero, but catch
4485 // it here in case it unexpectedly does. Don't try to
4486 // distinguish between the various exceptions because it seems
4487 // they vary by CPU, compiler and OS.
4488 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004489 }
4490 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004492 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004493#else
4494 return QCBOR_ERR_HW_FLOAT_DISABLED;
4495#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004496 break;
4497
4498 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004500 *pnValue = pItem->val.int64;
4501 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004502 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004503 }
4504 break;
4505
4506 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004507 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004508 if(pItem->val.uint64 < INT64_MAX) {
4509 *pnValue = pItem->val.int64;
4510 } else {
4511 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4512 }
4513 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004514 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004515 }
4516 break;
4517
4518 default:
4519 return QCBOR_ERR_UNEXPECTED_TYPE;
4520 }
4521 return QCBOR_SUCCESS;
4522}
4523
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004525void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004526 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004527 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004528 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004529{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004530 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004531 return;
4532 }
4533
Laurence Lundbladee6430642020-03-14 21:15:44 -07004534 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004535 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4536 if(uError) {
4537 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004538 return;
4539 }
4540
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004541 if(pItem) {
4542 *pItem = Item;
4543 }
4544
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004545 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004546}
4547
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004549void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4550 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004551 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004552 int64_t *pnValue,
4553 QCBORItem *pItem)
4554{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004555 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004556 if(pMe->uLastError != QCBOR_SUCCESS) {
4557 return;
4558 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004559
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004560 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004561}
4562
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004563
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004564void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4565 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004566 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004567 int64_t *pnValue,
4568 QCBORItem *pItem)
4569{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004570 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004571 if(pMe->uLastError != QCBOR_SUCCESS) {
4572 return;
4573 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004574
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004575 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004576}
4577
4578
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004579/*
4580 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004581
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004582 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583
Laurence Lundblade93d89472020-10-03 22:30:50 -07004584 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4585 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004586
4587 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4588
Laurence Lundblade93d89472020-10-03 22:30:50 -07004589 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4590 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004592static QCBORError
4593Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004594{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004595 switch(pItem->uDataType) {
4596
4597 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004598 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004599 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004600 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004602 }
4603 break;
4604
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004605 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004606 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004607 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004608 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004609 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004610 }
4611 break;
4612
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004613#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004614 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004615 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004616 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004617 pItem->val.expAndMantissa.nExponent,
4618 pnValue,
4619 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004620 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004621 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004622 }
4623 break;
4624
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004625 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004626 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004627 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004628 pItem->val.expAndMantissa.nExponent,
4629 pnValue,
4630 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004631 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004632 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004633 }
4634 break;
4635
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004636 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004637 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004638 int64_t nMantissa;
4639 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004640 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4641 if(uErr) {
4642 return uErr;
4643 }
4644 return ExponentiateNN(nMantissa,
4645 pItem->val.expAndMantissa.nExponent,
4646 pnValue,
4647 Exponentitate10);
4648 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004649 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004650 }
4651 break;
4652
4653 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004654 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004655 int64_t nMantissa;
4656 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004657 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4658 if(uErr) {
4659 return uErr;
4660 }
4661 return ExponentiateNN(nMantissa,
4662 pItem->val.expAndMantissa.nExponent,
4663 pnValue,
4664 Exponentitate10);
4665 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004667 }
4668 break;
4669
4670 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004671 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004672 int64_t nMantissa;
4673 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004674 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4675 if(uErr) {
4676 return uErr;
4677 }
4678 return ExponentiateNN(nMantissa,
4679 pItem->val.expAndMantissa.nExponent,
4680 pnValue,
4681 Exponentitate2);
4682 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004683 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004684 }
4685 break;
4686
4687 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004688 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004689 int64_t nMantissa;
4690 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004691 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4692 if(uErr) {
4693 return uErr;
4694 }
4695 return ExponentiateNN(nMantissa,
4696 pItem->val.expAndMantissa.nExponent,
4697 pnValue,
4698 Exponentitate2);
4699 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004701 }
4702 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004703#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004704
Laurence Lundbladee6430642020-03-14 21:15:44 -07004705
Laurence Lundbladec4537442020-04-14 18:53:22 -07004706 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004707 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004708}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004709
4710
Laurence Lundbladec4537442020-04-14 18:53:22 -07004711/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004712 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004713 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004715{
4716 QCBORItem Item;
4717
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004718 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004719
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004720 if(pMe->uLastError == QCBOR_SUCCESS) {
4721 // The above conversion succeeded
4722 return;
4723 }
4724
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004725 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004726 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004727 return;
4728 }
4729
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004730 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004731}
4732
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004733
4734/*
4735Public function, see header qcbor/qcbor_decode.h file
4736*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004737void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4738 int64_t nLabel,
4739 uint32_t uConvertTypes,
4740 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004741{
4742 QCBORItem Item;
4743
Laurence Lundblade93d89472020-10-03 22:30:50 -07004744 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4745 nLabel,
4746 uConvertTypes,
4747 pnValue,
4748 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004749
4750 if(pMe->uLastError == QCBOR_SUCCESS) {
4751 // The above conversion succeeded
4752 return;
4753 }
4754
4755 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4756 // The above conversion failed in a way that code below can't correct
4757 return;
4758 }
4759
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004760 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004761}
4762
4763
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764/*
4765Public function, see header qcbor/qcbor_decode.h file
4766*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004767void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4768 const char *szLabel,
4769 uint32_t uConvertTypes,
4770 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004771{
4772 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004773 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4774 szLabel,
4775 uConvertTypes,
4776 pnValue,
4777 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004778
4779 if(pMe->uLastError == QCBOR_SUCCESS) {
4780 // The above conversion succeeded
4781 return;
4782 }
4783
4784 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4785 // The above conversion failed in a way that code below can't correct
4786 return;
4787 }
4788
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004790}
4791
4792
Laurence Lundblade93d89472020-10-03 22:30:50 -07004793static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004794{
4795 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004796 case QCBOR_TYPE_DOUBLE:
4797 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004798#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004800 // Can't use llround here because it will not convert values
4801 // greater than INT64_MAX and less than UINT64_MAX that
4802 // need to be converted so it is more complicated.
4803 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4804 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4805 if(isnan(pItem->val.dfnum)) {
4806 return QCBOR_ERR_FLOAT_EXCEPTION;
4807 } else if(pItem->val.dfnum < 0) {
4808 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4809 } else {
4810 double dRounded = round(pItem->val.dfnum);
4811 // See discussion in DecodeDateEpoch() for
4812 // explanation of - 0x7ff
4813 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4814 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4815 }
4816 *puValue = (uint64_t)dRounded;
4817 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004818 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004819 if(isnan(pItem->val.fnum)) {
4820 return QCBOR_ERR_FLOAT_EXCEPTION;
4821 } else if(pItem->val.fnum < 0) {
4822 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4823 } else {
4824 float fRounded = roundf(pItem->val.fnum);
4825 // See discussion in DecodeDateEpoch() for
4826 // explanation of - 0x7ff
4827 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4828 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4829 }
4830 *puValue = (uint64_t)fRounded;
4831 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004832 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004833 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4834 // round() and roundf() shouldn't result in exceptions here, but
4835 // catch them to be robust and thorough. Don't try to
4836 // distinguish between the various exceptions because it seems
4837 // they vary by CPU, compiler and OS.
4838 return QCBOR_ERR_FLOAT_EXCEPTION;
4839 }
4840
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004841 } else {
4842 return QCBOR_ERR_UNEXPECTED_TYPE;
4843 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004844#else
4845 return QCBOR_ERR_HW_FLOAT_DISABLED;
4846#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004847 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004848
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004849 case QCBOR_TYPE_INT64:
4850 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4851 if(pItem->val.int64 >= 0) {
4852 *puValue = (uint64_t)pItem->val.int64;
4853 } else {
4854 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4855 }
4856 } else {
4857 return QCBOR_ERR_UNEXPECTED_TYPE;
4858 }
4859 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004861 case QCBOR_TYPE_UINT64:
4862 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4863 *puValue = pItem->val.uint64;
4864 } else {
4865 return QCBOR_ERR_UNEXPECTED_TYPE;
4866 }
4867 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004869 default:
4870 return QCBOR_ERR_UNEXPECTED_TYPE;
4871 }
4872
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 return QCBOR_SUCCESS;
4874}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004875
4876
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004877void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004878 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004880 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004881{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004882 if(pMe->uLastError != QCBOR_SUCCESS) {
4883 return;
4884 }
4885
Laurence Lundbladec4537442020-04-14 18:53:22 -07004886 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004887
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004888 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4889 if(uError) {
4890 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004891 return;
4892 }
4893
Laurence Lundbladea826c502020-05-10 21:07:00 -07004894 if(pItem) {
4895 *pItem = Item;
4896 }
4897
Laurence Lundblade93d89472020-10-03 22:30:50 -07004898 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004899}
4900
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004901
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004902void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004903 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004904 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905 uint64_t *puValue,
4906 QCBORItem *pItem)
4907{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004908 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004909 if(pMe->uLastError != QCBOR_SUCCESS) {
4910 return;
4911 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912
Laurence Lundblade93d89472020-10-03 22:30:50 -07004913 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914}
4915
4916
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004917void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004918 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004919 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004920 uint64_t *puValue,
4921 QCBORItem *pItem)
4922{
4923 if(pMe->uLastError != QCBOR_SUCCESS) {
4924 return;
4925 }
4926
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004927 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004928 if(pMe->uLastError != QCBOR_SUCCESS) {
4929 return;
4930 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004931
Laurence Lundblade93d89472020-10-03 22:30:50 -07004932 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004933}
4934
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004935
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004936
Laurence Lundblade93d89472020-10-03 22:30:50 -07004937static QCBORError
4938UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004940 switch(pItem->uDataType) {
4941
4942 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004943 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004944 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4945 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004946 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004947 }
4948 break;
4949
4950 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004951 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004952 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4953 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004954 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004955 }
4956 break;
4957
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004958#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004959
4960 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004961 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004962 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004963 pItem->val.expAndMantissa.nExponent,
4964 puValue,
4965 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004966 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004967 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004968 }
4969 break;
4970
4971 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004972 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4974 pItem->val.expAndMantissa.nExponent,
4975 puValue,
4976 Exponentitate2);
4977 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004978 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004979 }
4980 break;
4981
4982 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004983 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004984 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004985 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004986 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004987 if(uErr != QCBOR_SUCCESS) {
4988 return uErr;
4989 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004990 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004991 pItem->val.expAndMantissa.nExponent,
4992 puValue,
4993 Exponentitate10);
4994 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004995 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004996 }
4997 break;
4998
4999 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005000 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005001 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5002 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005003 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005004 }
5005 break;
5006
5007 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005008 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005009 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005010 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005011 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005012 if(uErr != QCBOR_SUCCESS) {
5013 return uErr;
5014 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005015 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016 pItem->val.expAndMantissa.nExponent,
5017 puValue,
5018 Exponentitate2);
5019 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005020 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005021 }
5022 break;
5023
5024 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005025 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005026 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5027 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005028 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005029 }
5030 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005031#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005032 default:
5033 return QCBOR_ERR_UNEXPECTED_TYPE;
5034 }
5035}
5036
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005037
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005038/*
5039 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005040 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005041void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005042{
5043 QCBORItem Item;
5044
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005045 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005046
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005047 if(pMe->uLastError == QCBOR_SUCCESS) {
5048 // The above conversion succeeded
5049 return;
5050 }
5051
5052 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5053 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005054 return;
5055 }
5056
Laurence Lundblade93d89472020-10-03 22:30:50 -07005057 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005058}
5059
Laurence Lundbladec4537442020-04-14 18:53:22 -07005060
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005061/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005062 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005063*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005064void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005065 int64_t nLabel,
5066 uint32_t uConvertTypes,
5067 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005068{
5069 QCBORItem Item;
5070
Laurence Lundblade93d89472020-10-03 22:30:50 -07005071 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5072 nLabel,
5073 uConvertTypes,
5074 puValue,
5075 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005076
5077 if(pMe->uLastError == QCBOR_SUCCESS) {
5078 // The above conversion succeeded
5079 return;
5080 }
5081
5082 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5083 // The above conversion failed in a way that code below can't correct
5084 return;
5085 }
5086
Laurence Lundblade93d89472020-10-03 22:30:50 -07005087 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005088}
5089
5090
5091/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005092 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005093*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005094void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005095 const char *szLabel,
5096 uint32_t uConvertTypes,
5097 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005098{
5099 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005100 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5101 szLabel,
5102 uConvertTypes,
5103 puValue,
5104 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005105
5106 if(pMe->uLastError == QCBOR_SUCCESS) {
5107 // The above conversion succeeded
5108 return;
5109 }
5110
5111 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5112 // The above conversion failed in a way that code below can't correct
5113 return;
5114 }
5115
Laurence Lundblade93d89472020-10-03 22:30:50 -07005116 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005117}
5118
5119
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005120
5121
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005122#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005123static QCBORError ConvertDouble(const QCBORItem *pItem,
5124 uint32_t uConvertTypes,
5125 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005126{
5127 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005128 case QCBOR_TYPE_FLOAT:
5129#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5130 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5131 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005132 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005133 *pdValue = (double)pItem->val.fnum;
5134 } else {
5135 return QCBOR_ERR_UNEXPECTED_TYPE;
5136 }
5137 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005138#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005139 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005140#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005141 break;
5142
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005143 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005144 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5145 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005146 *pdValue = pItem->val.dfnum;
5147 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005148 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005149 }
5150 }
5151 break;
5152
5153 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005154#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005155 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005156 // A simple cast seems to do the job with no worry of exceptions.
5157 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005158 *pdValue = (double)pItem->val.int64;
5159
5160 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005161 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005162 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005163#else
5164 return QCBOR_ERR_HW_FLOAT_DISABLED;
5165#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005166 break;
5167
5168 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005169#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005170 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005171 // A simple cast seems to do the job with no worry of exceptions.
5172 // There will be precision loss for some values.
5173 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005174 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005175 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005176 }
5177 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005178#else
5179 return QCBOR_ERR_HW_FLOAT_DISABLED;
5180#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005181
5182 default:
5183 return QCBOR_ERR_UNEXPECTED_TYPE;
5184 }
5185
5186 return QCBOR_SUCCESS;
5187}
5188
5189
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005190void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005191 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005192 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005193 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005194{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005195 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005196 return;
5197 }
5198
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005199 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005200
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005201 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005202 if(uError) {
5203 pMe->uLastError = (uint8_t)uError;
5204 return;
5205 }
5206
5207 if(pItem) {
5208 *pItem = Item;
5209 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005210
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005211 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005212}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005213
Laurence Lundbladec4537442020-04-14 18:53:22 -07005214
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005215void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5216 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005217 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005218 double *pdValue,
5219 QCBORItem *pItem)
5220{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005221 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005222 if(pMe->uLastError != QCBOR_SUCCESS) {
5223 return;
5224 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005225
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005226 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005227}
5228
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005229
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005230void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5231 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005232 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005233 double *pdValue,
5234 QCBORItem *pItem)
5235{
5236 if(pMe->uLastError != QCBOR_SUCCESS) {
5237 return;
5238 }
5239
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005240 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005241 if(pMe->uLastError != QCBOR_SUCCESS) {
5242 return;
5243 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005245 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005246}
5247
5248
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005249#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005250static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5251{
5252 double dResult;
5253
5254 dResult = 0.0;
5255 const uint8_t *pByte = BigNum.ptr;
5256 size_t uLen = BigNum.len;
5257 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005258 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005259 while(uLen--) {
5260 dResult = (dResult * 256.0) + (double)*pByte++;
5261 }
5262
5263 return dResult;
5264}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005265#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5266
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005267
Laurence Lundblade93d89472020-10-03 22:30:50 -07005268static QCBORError
5269DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005270{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005271#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005272 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005273 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5274 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5275 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005276 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005277
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005278#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005279 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005280 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005281 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005282 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5283 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5284 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005285 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005286 }
5287 break;
5288
5289 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005290 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005291 // Underflow gives 0, overflow gives infinity
5292 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5293 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005294 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005295 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005296 }
5297 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005298#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005299
5300 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005301 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005302 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5303 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005304 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005305 }
5306 break;
5307
5308 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005309 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005310 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005311 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005312 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005313 }
5314 break;
5315
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005316#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005317 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005318 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005319 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5320 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5321 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005322 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005323 }
5324 break;
5325
5326 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005327 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005328 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5329 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5330 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005331 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005332 }
5333 break;
5334
5335 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005336 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005337 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5338 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5339 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005340 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005341 }
5342 break;
5343
5344 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005345 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005346 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005347 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5348 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005349 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005350 }
5351 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005352#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005353
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005354 default:
5355 return QCBOR_ERR_UNEXPECTED_TYPE;
5356 }
5357
5358 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005359
5360#else
5361 (void)pItem;
5362 (void)uConvertTypes;
5363 (void)pdValue;
5364 return QCBOR_ERR_HW_FLOAT_DISABLED;
5365#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5366
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005367}
5368
5369
5370/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005371 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005372*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005373void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5374 uint32_t uConvertTypes,
5375 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005376{
5377
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005378 QCBORItem Item;
5379
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005380 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005381
5382 if(pMe->uLastError == QCBOR_SUCCESS) {
5383 // The above conversion succeeded
5384 return;
5385 }
5386
5387 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5388 // The above conversion failed in a way that code below can't correct
5389 return;
5390 }
5391
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005392 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005393}
5394
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005395
5396/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005397 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005398*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005399void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5400 int64_t nLabel,
5401 uint32_t uConvertTypes,
5402 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005403{
5404 QCBORItem Item;
5405
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005406 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005407
5408 if(pMe->uLastError == QCBOR_SUCCESS) {
5409 // The above conversion succeeded
5410 return;
5411 }
5412
5413 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5414 // The above conversion failed in a way that code below can't correct
5415 return;
5416 }
5417
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005418 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005419}
5420
5421
5422/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005423 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005424*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005425void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5426 const char *szLabel,
5427 uint32_t uConvertTypes,
5428 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005429{
5430 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005431 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005432
5433 if(pMe->uLastError == QCBOR_SUCCESS) {
5434 // The above conversion succeeded
5435 return;
5436 }
5437
5438 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5439 // The above conversion failed in a way that code below can't correct
5440 return;
5441 }
5442
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005443 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005444}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005445#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005446
5447
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448
5449
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005450#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005451static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5452{
5453 while((uInt & 0xff00000000000000UL) == 0) {
5454 uInt = uInt << 8;
5455 };
5456
5457 UsefulOutBuf UOB;
5458
5459 UsefulOutBuf_Init(&UOB, Buffer);
5460
5461 while(uInt) {
5462 const uint64_t xx = uInt & 0xff00000000000000UL;
5463 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5464 uInt = uInt << 8;
5465 (void)xx;
5466 }
5467
5468 return UsefulOutBuf_OutUBuf(&UOB);
5469}
5470
5471
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005472static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5473 TagSpecification TagSpec,
5474 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005475{
5476 QCBORError uErr;
5477 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005478 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005479 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005480 if(uErr != QCBOR_SUCCESS) {
5481 goto Done;
5482 }
5483
5484 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5485 break; // Successful exit. Moving on to finish decoding.
5486 }
5487
5488 // The item is an array, which means an undecoded
5489 // mantissa and exponent, so decode it. It will then
5490 // have a different type and exit the loop if.
5491 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5492 if(uErr != QCBOR_SUCCESS) {
5493 goto Done;
5494 }
5495
5496 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005497 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005498 }
5499Done:
5500 return uErr;
5501}
5502
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005503
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005504static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005505 TagSpecification TagSpec,
5506 QCBORItem *pItem,
5507 int64_t *pnMantissa,
5508 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005509{
5510 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005511
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005512 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005513 if(uErr != QCBOR_SUCCESS) {
5514 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005515 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005516
Laurence Lundblade9b334962020-08-27 10:55:53 -07005517 switch (pItem->uDataType) {
5518
5519 case QCBOR_TYPE_DECIMAL_FRACTION:
5520 case QCBOR_TYPE_BIGFLOAT:
5521 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5522 *pnExponent = pItem->val.expAndMantissa.nExponent;
5523 break;
5524
5525 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5526 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5527 *pnExponent = pItem->val.expAndMantissa.nExponent;
5528 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5529 break;
5530
5531 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5532 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5533 *pnExponent = pItem->val.expAndMantissa.nExponent;
5534 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5535 break;
5536
5537 default:
5538 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5539 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005540
5541 Done:
5542 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005543}
5544
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005545
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005546static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005547 TagSpecification TagSpec,
5548 QCBORItem *pItem,
5549 UsefulBuf BufferForMantissa,
5550 UsefulBufC *pMantissa,
5551 bool *pbIsNegative,
5552 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005553{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005554 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005555
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005556 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005557 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005558 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005559 }
5560
5561 uint64_t uMantissa;
5562
5563 switch (pItem->uDataType) {
5564
5565 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005566 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005567 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5568 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5569 *pbIsNegative = false;
5570 } else {
5571 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5572 *pbIsNegative = true;
5573 }
5574 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5575 *pnExponent = pItem->val.expAndMantissa.nExponent;
5576 break;
5577
5578 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005579 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005580 *pnExponent = pItem->val.expAndMantissa.nExponent;
5581 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5582 *pbIsNegative = false;
5583 break;
5584
5585 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005586 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005587 *pnExponent = pItem->val.expAndMantissa.nExponent;
5588 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5589 *pbIsNegative = true;
5590 break;
5591
5592 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005593 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005594 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005595
5596Done:
5597 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005598}
5599
5600
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005601/*
5602 Public function, see header qcbor/qcbor_decode.h file
5603*/
5604void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5605 uint8_t uTagRequirement,
5606 int64_t *pnMantissa,
5607 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005608{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005609 if(pMe->uLastError != QCBOR_SUCCESS) {
5610 return;
5611 }
5612
5613 QCBORItem Item;
5614 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5615 if(uError) {
5616 pMe->uLastError = (uint8_t)uError;
5617 return;
5618 }
5619
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005620 const TagSpecification TagSpec =
5621 {
5622 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005623 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5624 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5625 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005626 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005627
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005628 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005629}
5630
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005631
5632/*
5633 Public function, see header qcbor/qcbor_decode.h file
5634*/
5635void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005636 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005637 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005638 int64_t *pnMantissa,
5639 int64_t *pnExponent)
5640{
5641 if(pMe->uLastError != QCBOR_SUCCESS) {
5642 return;
5643 }
5644
5645 QCBORItem Item;
5646 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5647
5648 const TagSpecification TagSpec =
5649 {
5650 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005651 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5652 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5653 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005654 };
5655
5656 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5657}
5658
5659
5660/*
5661 Public function, see header qcbor/qcbor_decode.h file
5662*/
5663void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005664 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005665 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005666 int64_t *pnMantissa,
5667 int64_t *pnExponent)
5668{
5669 if(pMe->uLastError != QCBOR_SUCCESS) {
5670 return;
5671 }
5672
5673 QCBORItem Item;
5674 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5675
5676 const TagSpecification TagSpec =
5677 {
5678 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005679 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5680 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5681 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005682 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005684 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5685}
5686
5687
5688/*
5689 Public function, see header qcbor/qcbor_decode.h file
5690*/
5691void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5692 uint8_t uTagRequirement,
5693 UsefulBuf MantissaBuffer,
5694 UsefulBufC *pMantissa,
5695 bool *pbMantissaIsNegative,
5696 int64_t *pnExponent)
5697{
5698 if(pMe->uLastError != QCBOR_SUCCESS) {
5699 return;
5700 }
5701
5702 QCBORItem Item;
5703 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5704 if(uError) {
5705 pMe->uLastError = (uint8_t)uError;
5706 return;
5707 }
5708
5709 const TagSpecification TagSpec =
5710 {
5711 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005712 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5713 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5714 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005715 };
5716
Laurence Lundblade93d89472020-10-03 22:30:50 -07005717 ProcessMantissaAndExponentBig(pMe,
5718 TagSpec,
5719 &Item,
5720 MantissaBuffer,
5721 pMantissa,
5722 pbMantissaIsNegative,
5723 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005724}
5725
5726
5727/*
5728 Public function, see header qcbor/qcbor_decode.h file
5729*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005730void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005731 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005732 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005733 UsefulBuf BufferForMantissa,
5734 UsefulBufC *pMantissa,
5735 bool *pbIsNegative,
5736 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005737{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005738 if(pMe->uLastError != QCBOR_SUCCESS) {
5739 return;
5740 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005741
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005742 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005743 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005744 if(pMe->uLastError != QCBOR_SUCCESS) {
5745 return;
5746 }
5747
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005748 const TagSpecification TagSpec =
5749 {
5750 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005751 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5752 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5753 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005754 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005755
Laurence Lundblade93d89472020-10-03 22:30:50 -07005756 ProcessMantissaAndExponentBig(pMe,
5757 TagSpec,
5758 &Item,
5759 BufferForMantissa,
5760 pMantissa,
5761 pbIsNegative,
5762 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005763}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005764
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005765
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005766/*
5767 Public function, see header qcbor/qcbor_decode.h file
5768*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005769void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005770 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005771 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005772 UsefulBuf BufferForMantissa,
5773 UsefulBufC *pMantissa,
5774 bool *pbIsNegative,
5775 int64_t *pnExponent)
5776{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005777 if(pMe->uLastError != QCBOR_SUCCESS) {
5778 return;
5779 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005780
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005781 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005782 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5783 if(pMe->uLastError != QCBOR_SUCCESS) {
5784 return;
5785 }
5786
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005787 const TagSpecification TagSpec =
5788 {
5789 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005790 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5791 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5792 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005793 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005794
5795 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5796}
5797
5798
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005799/*
5800 Public function, see header qcbor/qcbor_decode.h file
5801*/
5802void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5803 uint8_t uTagRequirement,
5804 int64_t *pnMantissa,
5805 int64_t *pnExponent)
5806{
5807 if(pMe->uLastError != QCBOR_SUCCESS) {
5808 return;
5809 }
5810
5811 QCBORItem Item;
5812 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5813 if(uError) {
5814 pMe->uLastError = (uint8_t)uError;
5815 return;
5816 }
5817 const TagSpecification TagSpec =
5818 {
5819 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005820 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5821 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5822 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005823 };
5824
5825 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5826}
5827
5828
5829/*
5830 Public function, see header qcbor/qcbor_decode.h file
5831*/
5832void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005833 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005834 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005835 int64_t *pnMantissa,
5836 int64_t *pnExponent)
5837{
5838 if(pMe->uLastError != QCBOR_SUCCESS) {
5839 return;
5840 }
5841
5842 QCBORItem Item;
5843 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5844 if(pMe->uLastError != QCBOR_SUCCESS) {
5845 return;
5846 }
5847
5848 const TagSpecification TagSpec =
5849 {
5850 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005851 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5852 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5853 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005854 };
5855
5856 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5857}
5858
5859
5860/*
5861 Public function, see header qcbor/qcbor_decode.h file
5862*/
5863void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005864 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005865 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005866 int64_t *pnMantissa,
5867 int64_t *pnExponent)
5868{
5869 if(pMe->uLastError != QCBOR_SUCCESS) {
5870 return;
5871 }
5872
5873 QCBORItem Item;
5874 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5875 if(pMe->uLastError != QCBOR_SUCCESS) {
5876 return;
5877 }
5878
5879 const TagSpecification TagSpec =
5880 {
5881 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005882 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5883 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5884 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005885 };
5886
5887 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5888}
5889
5890
5891/*
5892 Public function, see header qcbor/qcbor_decode.h file
5893*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005894void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5895 uint8_t uTagRequirement,
5896 UsefulBuf MantissaBuffer,
5897 UsefulBufC *pMantissa,
5898 bool *pbMantissaIsNegative,
5899 int64_t *pnExponent)
5900{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005901 if(pMe->uLastError != QCBOR_SUCCESS) {
5902 return;
5903 }
5904
5905 QCBORItem Item;
5906 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5907 if(uError) {
5908 pMe->uLastError = (uint8_t)uError;
5909 return;
5910 }
5911
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005912 const TagSpecification TagSpec =
5913 {
5914 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005915 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5916 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5917 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005918 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005919
5920 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005921}
5922
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005923
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005924/*
5925 Public function, see header qcbor/qcbor_decode.h file
5926*/
5927void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005928 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005929 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005930 UsefulBuf BufferForMantissa,
5931 UsefulBufC *pMantissa,
5932 bool *pbIsNegative,
5933 int64_t *pnExponent)
5934{
5935 if(pMe->uLastError != QCBOR_SUCCESS) {
5936 return;
5937 }
5938
5939 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005940 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5941 if(pMe->uLastError != QCBOR_SUCCESS) {
5942 return;
5943 }
5944
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005945 const TagSpecification TagSpec =
5946 {
5947 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005948 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5949 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5950 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005951 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005952
Laurence Lundblade93d89472020-10-03 22:30:50 -07005953 ProcessMantissaAndExponentBig(pMe,
5954 TagSpec,
5955 &Item,
5956 BufferForMantissa,
5957 pMantissa,
5958 pbIsNegative,
5959 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005960}
5961
5962
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005963/*
5964 Public function, see header qcbor/qcbor_decode.h file
5965*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005966void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005967 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005968 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005969 UsefulBuf BufferForMantissa,
5970 UsefulBufC *pMantissa,
5971 bool *pbIsNegative,
5972 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005973{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005974 if(pMe->uLastError != QCBOR_SUCCESS) {
5975 return;
5976 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005977
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005978 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005979 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5980 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005981 return;
5982 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005983
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005984 const TagSpecification TagSpec =
5985 {
5986 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005987 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5988 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5989 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005990 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005991
Laurence Lundblade93d89472020-10-03 22:30:50 -07005992 ProcessMantissaAndExponentBig(pMe,
5993 TagSpec,
5994 &Item,
5995 BufferForMantissa,
5996 pMantissa,
5997 pbIsNegative,
5998 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005999}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006000
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006001#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */