blob: 4a20613d7c30c4e76e28dbe72c1ee20ad87866b5 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080049
Laurence Lundbladea9489f82020-09-12 13:50:56 -070050#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070051
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080053
54
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070055static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070056QCBORItem_IsMapOrArray(const QCBORItem *pMe)
57{
58 const uint8_t uDataType = pMe->uDataType;
59 return uDataType == QCBOR_TYPE_MAP ||
60 uDataType == QCBOR_TYPE_ARRAY ||
61 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
62}
63
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070064static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070065QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
66{
67 if(!QCBORItem_IsMapOrArray(pMe)){
68 return false;
69 }
70
71 if(pMe->val.uCount != 0) {
72 return false;
73 }
74 return true;
75}
76
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070077static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070078QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
79{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080080#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070081 if(!QCBORItem_IsMapOrArray(pMe)){
82 return false;
83 }
84
85 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
86 return false;
87 }
88 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080089#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
90 (void)pMe;
91 return false;
92#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070093}
94
95
Laurence Lundbladeee851742020-01-08 08:37:05 -080096/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070097 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080098 ===========================================================================*/
99
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
102 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700103 */
104
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700106static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700107DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700108{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700109 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800110 /* Limit in DecodeNesting_Descend against more than
111 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700113 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114}
115
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700116
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700117static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700118DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700120 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800121 /* Limit in DecodeNesting_Descend against more than
122 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700124 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700128static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700129DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
131 return pNesting->pCurrentBounded->u.ma.uStartOffset;
132}
133
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700134
Laurence Lundblade085d7952020-07-24 10:26:30 -0700135static inline bool
136DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
137{
138 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700146static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700150 return true;
151 } else {
152 return false;
153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154}
155
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700156
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700157static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159{
160 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800161 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800164
165#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700166 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800167 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700168 return false;
169 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800170
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800171#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
172
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800173 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174 return true;
175}
176
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700177static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700178DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700179{
180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800181 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700188static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
191 return true;
192 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700193 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194 return true;
195 }
196 return false;
197}
198
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700199
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700200static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800202 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700203 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800204 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
205 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
206 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700207 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700209
210 if(bIsEmpty) {
211 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
212 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700216static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700217{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700218 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700222static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224{
225 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800226 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800230 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700233 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800234 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700235 return false;
236 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800237 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800238 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
239 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800240 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700241 return false;
242 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800243 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700244 return true;
245}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700247
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700248static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700249DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800251 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
253 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700254 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700255 return false;
256 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257}
258
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700259
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700260static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
264 return true;
265 } else {
266 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700268}
269
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700270
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700271static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700272DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700273{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700274 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275 return false;
276 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
278 if(pNesting->pCurrentBounded->uLevelType != uType) {
279 return false;
280 }
281
282 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700283}
284
Laurence Lundblade02625d42020-06-25 14:41:41 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700287DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700288{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800289 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700290 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700291}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700292
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700295DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
296{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800297 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700298 pNesting->pCurrent->u.ma.uCountCursor++;
299}
300
301
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700302static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700303DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
304{
305 pNesting->pCurrent--;
306}
307
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308
309static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700310DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800312 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700313 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700314 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 }
316
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800317 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700318 pNesting->pCurrent++;
319
320 pNesting->pCurrent->uLevelType = uType;
321
322 return QCBOR_SUCCESS;
323}
324
325
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700326static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
328 bool bIsEmpty,
329 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700330{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700331 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800332 * Should only be called on map/array.
333 *
334 * Have descended into this before this is called. The job here is
335 * just to mark it in bounded mode.
336 *
337 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
338 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
339 *
340 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700341 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800342 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700343 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700344 }
345
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700346 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700347
348 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349
350 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700351}
352
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700353
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700354static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700355DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 uint8_t uQCBORType,
357 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700359 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360
361 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800362 /* Nothing to do for empty definite-length arrays. They are just are
363 * effectively the same as an item that is not a map or array.
364 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800366 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700367 }
368
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800369 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700370 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
371 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700372 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373 goto Done;
374 }
375
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700376 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800381 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700382 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
383 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384
385 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700386
387Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 return uError;;
389}
390
391
392static inline void
393DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
394{
395 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
396}
397
398
399static inline void
400DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
401{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700402 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700403 pNesting->pCurrentBounded--;
404 if(DecodeNesting_IsCurrentBounded(pNesting)) {
405 break;
406 }
407 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700408}
409
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800410
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700411static inline void
412DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
413{
414 pNesting->pCurrent = pNesting->pCurrentBounded;
415}
416
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700417
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700418static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700420 uint32_t uEndOffset,
421 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700423 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700425 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427 goto Done;
428 }
429
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800430 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700431 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
432 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700433
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800434 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435 pNesting->pCurrentBounded = pNesting->pCurrent;
436
437Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438 return uError;;
439}
440
Laurence Lundbladed0304932020-06-27 10:59:38 -0700441
442static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700443DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444{
445 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446}
447
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700448
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700449static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800450DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
451{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700452 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
453 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
454 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455}
456
457
458static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700460{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700461 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700462 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
463 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700464}
465
466
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700467static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800468DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
469 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700470{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700471 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700472}
473
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800476DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
477 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700478{
479 *pNesting = *pSave;
480}
481
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700482
Laurence Lundblade02625d42020-06-25 14:41:41 -0700483static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700484DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700485{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700486 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487}
488
489
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800490
491
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800492#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800493/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
495
496 The following four functions are pretty wrappers for invocation of
497 the string allocator supplied by the caller.
498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500
Laurence Lundbladeee851742020-01-08 08:37:05 -0800501static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800502StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800503{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800504 /* These pragmas allow the "-Wcast-qual" warnings flag to be set for
505 * gcc and clang. This is the one place where the const needs to be
506 * cast away so const can be use in the rest of the code.
507 */
508#pragma GCC diagnostic push
509#pragma GCC diagnostic ignored "-Wcast-qual"
510 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
511#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512}
513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514// StringAllocator_Reallocate called with pMem NULL is
515// equal to StringAllocator_Allocate()
516static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800517StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800518 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800521 /* See comment in StringAllocator_Free() */
522#pragma GCC diagnostic push
523#pragma GCC diagnostic ignored "-Wcast-qual"
524 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
525#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800529StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530{
531 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
532}
533
Laurence Lundbladeee851742020-01-08 08:37:05 -0800534static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800535StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800536{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800537 /* See comment in StringAllocator_Free() */
538#pragma GCC diagnostic push
539#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540 if(pMe->pfAllocator) {
541 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
542 }
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800543#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800545#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546
547
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800548
549
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550/*===========================================================================
551 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800553 See qcbor/qcbor_decode.h for definition of the object
554 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800555 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800557 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800559void QCBORDecode_Init(QCBORDecodeContext *pMe,
560 UsefulBufC EncodedCBOR,
561 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800563 memset(pMe, 0, sizeof(QCBORDecodeContext));
564 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
565 /* Don't bother with error check on decode mode. If a bad value is
566 * passed it will just act as if the default normal mode of 0 was set.
567 */
568 pMe->uDecodeMode = (uint8_t)nDecodeMode;
569 DecodeNesting_Init(&(pMe->nesting));
570
571 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
572 * GetNext_TaggedItem() and MapTagNumber(). */
573 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574}
575
576
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800577#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
578
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800580 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
583 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800584 void *pAllocateContext,
585 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
588 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
589 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700590}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800591#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800594
595
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800596/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800597 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800598 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800599void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800602 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700603 (void)pMe;
604 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700605}
606
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700607
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800608
609
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700610/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800611 * Decoding items is done in six layers, one calling the next one
612 * down. If a layer has no work to do for a particular item, it
613 * returns quickly.
614 *
615 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
616 * data items, turning them into the local C representation. For the
617 * most simple it is just associating a QCBOR_TYPE with the data. For
618 * the complex ones that an aggregate of data items, there is some
619 * further decoding and some limited recursion.
620 *
621 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
622 * ends of maps and arrays. It tracks descending into and ascending
623 * out of maps/arrays. It processes breaks that terminate
624 * indefinite-length maps and arrays.
625 *
626 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
627 * items, the label and the data, that make up a map entry. It only
628 * does work on maps. It combines the label and data items into one
629 * labeled item.
630 *
631 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
632 * numbers. It turns the tag numbers into bit flags associated with
633 * the data item. No actual decoding of the contents of the tag is
634 * performed here.
635 *
636 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
637 * that make up an indefinite-length string into one string item. It
638 * uses the string allocator to create contiguous space for the
639 * item. It processes all breaks that are part of indefinite-length
640 * strings.
641 *
642 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
643 * CBOR. Each atomic data item has a "major type", an integer
644 * "argument" and optionally some content. For text and byte strings,
645 * the content is the bytes that make up the string. These are the
646 * smallest data items that are considered to be well-formed. The
647 * content may also be other data items in the case of aggregate
648 * types. They are not handled in this layer.
649 *
650 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
651 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800653
654
655/*
656 * Note about use of int and unsigned variables.
657 *
658 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
659 * used carefully here, and in particular why it isn't used in the
660 * public interface. Also see
661 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
662 *
663 * Int is used for values that need less than 16-bits and would be
664 * subject to integer promotion and result in complaining from static
665 * analyzers.
666 */
667
668
669/**
670 * @brief Decode the CBOR head, the type and argument.
671 *
672 * @param[in] pUInBuf The input buffer to read from.
673 * @param[out] pnMajorType The decoded major type.
674 * @param[out] puArgument The decoded argument.
675 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
676 *
677 * @retval QCBOR_ERR_UNSUPPORTED
678 * @retval QCBOR_ERR_HIT_END
679 *
680 * This decodes the CBOR "head" that every CBOR data item has. See
681 * longer explaination of the head in documentation for
682 * QCBOREncode_EncodeHead().
683 *
684 * This does the network->host byte order conversion. The conversion
685 * here also results in the conversion for floats in addition to that
686 * for lengths, tags and integer values.
687 *
688 * The int type is preferred to uint8_t for some variables as this
689 * avoids integer promotions, can reduce code size and makes static
690 * analyzers happier.
691 */
692static inline QCBORError
693DecodeHead(UsefulInputBuf *pUInBuf,
694 int *pnMajorType,
695 uint64_t *puArgument,
696 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800698 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800700 /* Get the initial byte that every CBOR data item has and break it
701 * down. */
702 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800703 const int nTmpMajorType = nInitialByte >> 5;
704 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800705
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800706 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800707 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800708
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800709 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800710 /* Need to get 1,2,4 or 8 additional argument bytes. Map
711 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
712 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800713 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800715 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800716 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800717 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800718 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800719 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
720 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 /* The reserved and thus-far unused additional info values */
723 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800724 goto Done;
725 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800726 /* Less than 24, additional info is argument or 31, an
727 * indefinite-length. No more bytes to get.
728 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800733 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734 goto Done;
735 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800736
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800737 /* All successful if arrived here. */
738 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800739 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800740 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800744 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745}
746
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800748/**
749 * @brief Decode integer types, major types 0 and 1.
750 *
751 * @param[in] nMajorType The CBOR major type (0 or 1).
752 * @param[in] uArgument The argument from the head.
753 * @param[out] pDecodedItem The filled in decoded item.
754 *
755 * @retval QCBOR_ERR_INT_OVERFLOW
756 *
757 * Must only be called when major type is 0 or 1.
758 *
759 * CBOR doesn't explicitly specify two's compliment for integers but
760 * all CPUs use it these days and the test vectors in the RFC are
761 * so. All integers in the CBOR structure are positive and the major
762 * type indicates positive or negative. CBOR can express positive
763 * integers up to 2^x - 1 where x is the number of bits and negative
764 * integers down to 2^x. Note that negative numbers can be one more
765 * away from zero than positive. Stdint, as far as I can tell, uses
766 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700768static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800769DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800771 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800774 if (uArgument <= INT64_MAX) {
775 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800777
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800779 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800784 if(uArgument <= INT64_MAX) {
785 /* CBOR's representation of negative numbers lines up with
786 * the two-compliment representation. A negative integer has
787 * one more in range than a positive integer. INT64_MIN is
788 * equal to (-INT64_MAX) - 1.
789 */
790 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800794 /* C can't represent a negative integer in this range so it
795 * is an error.
796 */
797 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 }
799 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802}
803
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800804
805/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
807#error QCBOR_TYPE_FALSE macro value wrong
808#endif
809
810#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
811#error QCBOR_TYPE_TRUE macro value wrong
812#endif
813
814#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
815#error QCBOR_TYPE_NULL macro value wrong
816#endif
817
818#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
819#error QCBOR_TYPE_UNDEF macro value wrong
820#endif
821
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700822#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
823#error QCBOR_TYPE_BREAK macro value wrong
824#endif
825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
827#error QCBOR_TYPE_DOUBLE macro value wrong
828#endif
829
830#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
831#error QCBOR_TYPE_FLOAT macro value wrong
832#endif
833
Laurence Lundblade9b334962020-08-27 10:55:53 -0700834
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835/**
836 * @brief Decode major type 7 -- true, false, floating-point, break...
837 *
838 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
839 * @param[in] uArgument The argument from the head.
840 * @param[out] pDecodedItem The filled in decoded item.
841 *
842 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200843 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800844 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847static inline QCBORError
848DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
849{
850 QCBORError uReturn = QCBOR_SUCCESS;
851
852 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
853 * checks above make sure uAdditionalInfo values line up with
854 * uDataType values. DecodeHead() never returns an AdditionalInfo
855 * > 0x1f so cast is safe.
856 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800859 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800860 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
861 * are caught before this is called.
862 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700865#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800866 /* Half-precision is returned as a double. The cast to
867 * uint16_t is safe because the encoded value was 16 bits. It
868 * was widened to 64 bits to be passed in here.
869 */
870 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700871 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800872#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200873 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700874 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800875 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200876#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 /* Single precision is normally returned as a double since
878 * double is widely supported, there is no loss of precision,
879 * it makes it easy for the caller in most cases and it can
880 * be converted back to single with no loss of precision
881 *
882 * The cast to uint32_t is safe because the encoded value was
883 * 32 bits. It was widened to 64 bits to be passed in here.
884 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800886 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700887#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800888 /* In the normal case, use HW to convert float to
889 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700890 pDecodedItem->val.dfnum = (double)f;
891 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800892#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800893 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894 pDecodedItem->val.fnum = f;
895 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
896
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800897 /* IEEE754_FloatToDouble() could be used here to return as
898 * a double, but it adds object code and most likely
899 * anyone disabling FLOAT HW use doesn't care about floats
900 * and wants to save object code.
901 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800902#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700903 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200904#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
905 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700906 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700907
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800908 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200909#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800910 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700911 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200912#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
913 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700914 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800916 case CBOR_SIMPLEV_FALSE: /* 20 */
917 case CBOR_SIMPLEV_TRUE: /* 21 */
918 case CBOR_SIMPLEV_NULL: /* 22 */
919 case CBOR_SIMPLEV_UNDEF: /* 23 */
920 case CBOR_SIMPLE_BREAK: /* 31 */
921 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800923 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
924 if(uArgument <= CBOR_SIMPLE_BREAK) {
925 /* This takes out f8 00 ... f8 1f which should be encoded
926 * as e0 … f7
927 */
928 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929 goto Done;
930 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800931 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800933 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 /* DecodeHead() will make uArgument equal to
936 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
937 * safe because the 2, 4 and 8 byte lengths of uNumber are in
938 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800939 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800940 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 break;
942 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800945 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946}
947
948
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800949/**
950 * @brief Decode text and byte strings
951 *
952 * @param[in] pAllocator The string allocator or NULL.
953 * @param[in] uStrLen The length of the string.
954 * @param[in] pUInBuf The surce from which to read the string's bytes.
955 * @param[out] pDecodedItem The filled in decoded item.
956 *
957 * @retval QCBOR_ERR_HIT_END
958 * @retval QCBOR_ERR_STRING_ALLOCATE
959 * @retval QCBOR_ERR_STRING_TOO_LONG
960 *
961 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
962 * pDecodedItem. If @c pAllocator is not NULL then memory for the
963 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800965static inline QCBORError
966DecodeBytes(const QCBORInternalAllocator *pAllocator,
967 uint64_t uStrLen,
968 UsefulInputBuf *pUInBuf,
969 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800971 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800973 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
974 * CPUs. This check makes the casts to size_t below safe.
975 *
976 * The max is 4 bytes less than the largest sizeof() so this can be
977 * tested by putting a SIZE_MAX length in the CBOR test input (no
978 * one will care the limit on strings is 4 bytes shorter).
979 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800980 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800981 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800982 goto Done;
983 }
984
985 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530986 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800987 /* Failed to get the bytes for this string item */
988 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530989 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530991
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800992#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 /* Note that this is not where allocation to coalesce
994 * indefinite-length strings is done. This is for when the caller
995 * has requested all strings be allocated. Disabling indefinite
996 * length strings also disables this allocate-all option.
997 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800998 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800999 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301001 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001002 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301003 goto Done;
1004 }
1005 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001006 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001007 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301008 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001009#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1010 (void)pAllocator;
1011#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1012
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001013 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001014 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301016Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001017 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018}
1019
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001020
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001021/**
1022 * @brief Map the CBOR major types for strings to the QCBOR types.
1023 *
1024 * @param[in] nCBORMajorType The CBOR major type to convert.
1025 * @retturns QCBOR type number.
1026 *
1027 * This only works for the two string types.
1028 */
1029static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001030{
1031 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1032 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1033 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001035 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1036 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1037 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001038
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001039 return (uint8_t)(nCBORMajorType + 4);
1040}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041
1042
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001043/**
1044 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1045 *
1046 * @param[in] nCBORMajorType The CBOR major type to convert.
1047 * @retturns QCBOR type number.
1048 *
1049 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001051static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001053 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1054 #error QCBOR_TYPE_ARRAY value not lined up with major type
1055 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001057 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1058 #error QCBOR_TYPE_MAP value not lined up with major type
1059 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001060
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001061 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062}
1063
1064
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001065/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001066 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001067 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001068 * @param[in] pUInBuf Input buffer to read data item from.
1069 * @param[out] pDecodedItem The filled-in decoded item.
1070 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001071 *
1072 * @retval QCBOR_ERR_UNSUPPORTED
1073 * @retval QCBOR_ERR_HIT_END
1074 * @retval QCBOR_ERR_INT_OVERFLOW
1075 * @retval QCBOR_ERR_STRING_ALLOCATE
1076 * @retval QCBOR_ERR_STRING_TOO_LONG
1077 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001078 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1081 *
1082 * This decodes the most primitive / atomic data item. It does
1083 * no combing of data items.
1084 */
1085static QCBORError
1086DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1087 QCBORItem *pDecodedItem,
1088 const QCBORInternalAllocator *pAllocator)
1089{
1090 QCBORError uReturn;
1091
1092 /* Get the major type and the argument. The argument could be
1093 * length of more bytes or the value depending on the major
1094 * type. nAdditionalInfo is an encoding of the length of the
1095 * uNumber and is needed to decode floats and doubles.
1096 */
1097 int nMajorType = 0;
1098 uint64_t uArgument = 0;
1099 int nAdditionalInfo = 0;
1100
1101 memset(pDecodedItem, 0, sizeof(QCBORItem));
1102
1103 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1104 if(uReturn) {
1105 goto Done;
1106 }
1107
1108 /* At this point the major type and the argument are valid. We've
1109 * got the type and the argument that starts every CBOR data item.
1110 */
1111 switch (nMajorType) {
1112 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1113 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1114 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1115 uReturn = QCBOR_ERR_BAD_INT;
1116 } else {
1117 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1118 }
1119 break;
1120
1121 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1122 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1123 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1124 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1125 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1126 } else {
1127 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1128 }
1129 break;
1130
1131 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1132 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1133 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1134 /* Indefinite-length string. */
1135#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1136 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1137#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1138 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1139 break;
1140#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1141 } else {
1142 /* Definite-length string. */
1143 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1144 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1145 goto Done;
1146 }
1147 /* cast OK because of check above */
1148 pDecodedItem->val.uCount = (uint16_t)uArgument;
1149 }
1150 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1151 break;
1152
1153 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1154 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1155 uReturn = QCBOR_ERR_BAD_INT;
1156 } else {
1157 pDecodedItem->val.uTagV = uArgument;
1158 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1159 }
1160 break;
1161
1162 case CBOR_MAJOR_TYPE_SIMPLE:
1163 /* Major type 7: float, double, true, false, null... */
1164 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1165 break;
1166
1167 default:
1168 /* Never happens because DecodeHead() should never return > 7 */
1169 uReturn = QCBOR_ERR_UNSUPPORTED;
1170 break;
1171 }
1172
1173Done:
1174 return uReturn;
1175}
1176
1177
1178/**
1179 * @brief Process indefinite-length strings (decode layer 5).
1180 *
1181 * @param[in] pMe Decoder context
1182 * @param[out] pDecodedItem The decoded item that work is done on.
1183 *
1184 * @retval QCBOR_ERR_UNSUPPORTED
1185 * @retval QCBOR_ERR_HIT_END
1186 * @retval QCBOR_ERR_INT_OVERFLOW
1187 * @retval QCBOR_ERR_STRING_ALLOCATE
1188 * @retval QCBOR_ERR_STRING_TOO_LONG
1189 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001190 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001191 * @retval QCBOR_ERR_BAD_TYPE_7
1192 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1194 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001195 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001196 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001197 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001199 * If it is, this loops getting the subsequent chunk data items that
1200 * make up the string. The string allocator is used to make a
1201 * contiguous buffer for the chunks. When this completes @c
1202 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001203 *
1204 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001205 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001206static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001208{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001209 /* Aproximate stack usage
1210 * 64-bit 32-bit
1211 * local vars 32 16
1212 * 2 UsefulBufs 32 16
1213 * QCBORItem 56 52
1214 * TOTAL 120 74
1215 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001216
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001218 * coalescing the chunks of an indefinite-length string, 2)
1219 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001220 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001221 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001222 * strings cannot be processed at all without a string allocator.
1223 *
1224 * The second used is in DecodeBytes() which is called by
1225 * GetNext_Item() below. This second use unneccessary for most use
1226 * and only happens when requested in the call to
1227 * QCBORDecode_SetMemPool(). If the second use not requested then
1228 * NULL is passed for the string allocator to GetNext_Item().
1229 *
1230 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1231 * allocator altogether and thus both of these uses. It reduced the
1232 * decoder object code by about 400 bytes.
1233 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001234 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001235
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001237 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001238
1239 if(pMe->StringAllocator.pfAllocator) {
1240 pAllocator = &(pMe->StringAllocator);
1241 if(pMe->bStringAllocateAll) {
1242 pAllocatorForGetNext = pAllocator;
1243 }
1244 }
1245#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1246
1247 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001248 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001249 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001250 goto Done;
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001253 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001254 const uint8_t uStringType = pDecodedItem->uDataType;
1255 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001256 goto Done;
1257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001258
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001259 /* Is this a string with an indefinite length? */
1260 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1261 goto Done;
1262 }
1263
1264#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001265 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001266 if(pAllocator == NULL) {
1267 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1268 goto Done;
1269 }
1270
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001271 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001272 UsefulBufC FullString = NULLUsefulBufC;
1273
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001275 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001276 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001277 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001278 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279 * be allocated. They are always copied in the the contiguous
1280 * buffer allocated here.
1281 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001282 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001283 if(uReturn) {
1284 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001286
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001287 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001288 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001289 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001290 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301291 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001292 break;
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001296 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001300 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001301 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1302 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303 break;
1304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001306 /* The first time throurgh FullString.ptr is NULL and this is
1307 * equivalent to StringAllocator_Allocate(). Subsequently it is
1308 * not NULL and a reallocation happens.
1309 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001310 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001311 FullString.ptr,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001312 FullString.len + StringChunkItem.val.string.len);
1313
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001315 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001316 break;
1317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001318
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001319 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001320 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001321 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001322
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001323 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1324 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001325 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001326 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001327#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1328 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1329#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001330
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001331Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001332 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001333}
1334
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001335
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001336/**
1337 * @brief This converts a tag number to a shorter mapped value for storage.
1338 *
1339 * @param[in] pMe The decode context.
1340 * @param[in] uUnMappedTag The tag number to map
1341 * @param[out] puMappedTagNumer The stored tag number.
1342 *
1343 * @return error code.
1344 *
1345 * The main point of mapping tag numbers is make QCBORItem
1346 * smaller. With this mapping storage of 4 tags takes up 8
1347 * bytes. Without, it would take up 32 bytes.
1348 *
1349 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1350 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1351 *
1352 * See also UnMapTagNumber() and @ref QCBORItem.
1353 */
1354static inline QCBORError
1355MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1356{
1357 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1358 unsigned uTagMapIndex;
1359 /* Is there room in the tag map, or is it in it already? */
1360 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1361 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1362 break;
1363 }
1364 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1365 break;
1366 }
1367 }
1368 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1369 return QCBOR_ERR_TOO_MANY_TAGS;
1370 }
1371
1372 /* Covers the cases where tag is new and were it is already in the map */
1373 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1374 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1375
1376 } else {
1377 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1378 }
1379
1380 return QCBOR_SUCCESS;
1381}
1382
1383
1384/**
1385 * @brief This converts a mapped tag number to the actual tag number.
1386 *
1387 * @param[in] pMe The decode context.
1388 * @param[in] uMappedTagNumber The stored tag number.
1389 *
1390 * @return The actual tag number is returned or
1391 * @ref CBOR_TAG_INVALID64 on error.
1392 *
1393 * This is the reverse of MapTagNumber()
1394 */
1395static uint64_t
1396UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1397{
1398 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1399 return uMappedTagNumber;
1400 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001401 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001402 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001403 /* This won't be negative because of code below in
1404 * MapTagNumber()
1405 */
1406 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1407 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001408 }
1409}
1410
Laurence Lundblade9b334962020-08-27 10:55:53 -07001411
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001412/**
1413 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1414 *
1415 * @param[in] pMe Decoder context
1416 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001417
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001418 * @retval QCBOR_ERR_UNSUPPORTED
1419 * @retval QCBOR_ERR_HIT_END
1420 * @retval QCBOR_ERR_INT_OVERFLOW
1421 * @retval QCBOR_ERR_STRING_ALLOCATE
1422 * @retval QCBOR_ERR_STRING_TOO_LONG
1423 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001424 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001425 * @retval QCBOR_ERR_BAD_TYPE_7
1426 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1427 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1428 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1429 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1430 * @retval QCBOR_ERR_TOO_MANY_TAGS
1431 *
1432 * This loops getting atomic data items until one is not a tag
1433 * number. Usually this is largely pass-through because most
1434 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001435 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001436static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001437QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001438{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1440
1441 /* Initialize to CBOR_TAG_INVALID16 */
1442 #if CBOR_TAG_INVALID16 != 0xffff
1443 /* Be sure the memset does the right thing. */
1444 #err CBOR_TAG_INVALID16 tag not defined as expected
1445 #endif
1446 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001447
Laurence Lundblade9b334962020-08-27 10:55:53 -07001448 QCBORError uReturn = QCBOR_SUCCESS;
1449
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001450 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001451 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001452 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001453 if(uErr != QCBOR_SUCCESS) {
1454 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001456 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001457
Laurence Lundblade9b334962020-08-27 10:55:53 -07001458 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001459 /* Successful exit from loop; maybe got some tags, maybe not */
1460 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001461 break;
1462 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001463
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001464 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1465 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001466 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001467 /* Continue on to get all tags wrapping this item even though
1468 * it is erroring out in the end. This allows decoding to
1469 * continue. This is a resource limit error, not a problem
1470 * with being well-formed CBOR.
1471 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001472 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001473 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001474 /* Slide tags over one in the array to make room at index 0.
1475 * Must use memmove because the move source and destination
1476 * overlap.
1477 */
1478 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001479
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001480 /* Map the tag */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001481 uint16_t uMappedTagNumer = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001482 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1483 /* Continue even on error so as to consume all tags wrapping
1484 * this data item so decoding can go on. If MapTagNumber()
1485 * errors once it will continue to error.
1486 */
1487 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001488 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001489
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001490Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001491 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001492}
1493
1494
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001495/**
1496 * @brief Combine a map entry label and value into one item (decode layer 3).
1497 *
1498 * @param[in] pMe Decoder context
1499 * @param[out] pDecodedItem The decoded item that work is done on.
1500 *
1501 * @retval QCBOR_ERR_UNSUPPORTED
1502 * @retval QCBOR_ERR_HIT_END
1503 * @retval QCBOR_ERR_INT_OVERFLOW
1504 * @retval QCBOR_ERR_STRING_ALLOCATE
1505 * @retval QCBOR_ERR_STRING_TOO_LONG
1506 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001507 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001508 * @retval QCBOR_ERR_BAD_TYPE_7
1509 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1510 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1511 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1512 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1513 * @retval QCBOR_ERR_TOO_MANY_TAGS
1514 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1515 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1516 *
1517 * If a the current nesting level is a map, then this
1518 * combines pairs of items into one data item with a label
1519 * and value.
1520 *
1521 * This is pass-through if the current nesting leve is
1522 * not a map.
1523 *
1524 * This also implements maps-as-array mode where a map
1525 * is treated like an array to allow caller to do their
1526 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001527 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001528static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001529QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001530{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001531 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1532 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001533 goto Done;
1534 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1537 /* Break can't be a map entry */
1538 goto Done;
1539 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001540
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001541 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1542 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001543
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001544 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1545 /* Save label in pDecodedItem and get the next which will
1546 * be the real data item.
1547 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001548 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001549 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1550 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001551 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001552 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001553
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301554 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001555
1556 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001557 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001558 pDecodedItem->label.string = LabelItem.val.string;
1559 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001560 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1561 /* It's not a string and we only want strings */
1562 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001563 goto Done;
1564 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1565 pDecodedItem->label.int64 = LabelItem.val.int64;
1566 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1567 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1568 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1569 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1570 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1571 pDecodedItem->label.string = LabelItem.val.string;
1572 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1573 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1574 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001575 /* label is not an int or a string. It is an arrray
1576 * or a float or such and this implementation doesn't handle that.
1577 * Also, tags on labels are ignored.
1578 */
1579 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001580 goto Done;
1581 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001582 }
1583 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001584 /* Decoding of maps as arrays to let the caller decide what to do
1585 * about labels, particularly lables that are not integers or
1586 * strings.
1587 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001588 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001589 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001590 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001591 goto Done;
1592 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001593 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1595 * Cast is needed because of integer promotion.
1596 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001597 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001598 }
1599 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001600
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001601Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001602 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001603}
1604
1605
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001606#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001607/**
1608 * @brief Peek and see if next data item is a break;
1609 *
1610 * @param[in] pUIB UsefulInputBuf to read from.
1611 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1612 *
1613 * @return Any decoding error.
1614 *
1615 * See if next item is a CBOR break. If it is, it is consumed,
1616 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001617*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001618static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001619NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1620{
1621 *pbNextIsBreak = false;
1622 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001623 QCBORItem Peek;
1624 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001625 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001626 if(uReturn != QCBOR_SUCCESS) {
1627 return uReturn;
1628 }
1629 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001630 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001631 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001632 } else {
1633 *pbNextIsBreak = true;
1634 }
1635 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001636
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001637 return QCBOR_SUCCESS;
1638}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001639#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001640
1641
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001642/**
1643 * @brief Ascend up nesting levels if all items in them have been consumed.
1644 *
1645 * @param[in] pMe The decode context.
1646 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1647 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001648 * An item was just consumed, now figure out if it was the
1649 * end of an array/map map that can be closed out. That
1650 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001651*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001652static QCBORError
1653QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001654{
1655 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001656
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001657 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1659
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001660 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1661 /* Nesting level is bstr-wrapped CBOR */
1662
1663 /* Ascent for bstr-wrapped CBOR is always by explicit call
1664 * so no further ascending can happen.
1665 */
1666 break;
1667
1668 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1669 /* Level is a definite-length array/map */
1670
1671 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001672 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1673 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001674 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001675 break;
1676 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001677 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001678 * is time to ascend one level. This happens below.
1679 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001680
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001681#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001682 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001683 /* Level is an indefinite-length array/map. */
1684
1685 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001686 bool bIsBreak = false;
1687 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1688 if(uReturn != QCBOR_SUCCESS) {
1689 goto Done;
1690 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001691
1692 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001693 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001694 break;
1695 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001697 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001698 * it is time to ascend one level.
1699 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001700
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001701#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001702 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001703
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001704
1705 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706
Laurence Lundblade93d89472020-10-03 22:30:50 -07001707 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001708 * QCBORDecode_ExitBoundedMode().
1709 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001710 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001711 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001712 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001713 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001714 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001715 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001716
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001717 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001718 break;
1719 }
1720
1721 /* Finally, actually ascend one level. */
1722 DecodeNesting_Ascend(&(pMe->nesting));
1723 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001724
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001725 uReturn = QCBOR_SUCCESS;
1726
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001727#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001728Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001729#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1730
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001731 return uReturn;
1732}
1733
1734
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001735/**
1736 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1737 *
1738 * @param[in] pMe Decoder context
1739 * @param[out] pDecodedItem The decoded item that work is done on.
1740 *
1741 * @retval QCBOR_ERR_UNSUPPORTED
1742 * @retval QCBOR_ERR_HIT_END
1743 * @retval QCBOR_ERR_INT_OVERFLOW
1744 * @retval QCBOR_ERR_STRING_ALLOCATE
1745 * @retval QCBOR_ERR_STRING_TOO_LONG
1746 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001747 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001748 * @retval QCBOR_ERR_BAD_TYPE_7
1749 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1750 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1751 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1752 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1753 * @retval QCBOR_ERR_TOO_MANY_TAGS
1754 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1755 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1756 * @retval QCBOR_ERR_NO_MORE_ITEMS
1757 * @retval QCBOR_ERR_BAD_BREAK
1758 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1759 *
1760 * This handles the traversal descending into and asecnding out of
1761 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1762 * definite- and indefinte-length maps and arrays by looking at the
1763 * item count or finding CBOR breaks. It detects the ends of the
1764 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001765 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001766static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001767QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001768{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001769 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001770 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001771
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001772 /* If out of bytes to consume, it is either the end of the
1773 * top-level sequence of some bstr-wrapped CBOR that was entered.
1774 *
1775 * In the case of bstr-wrapped CBOR, the length of the
1776 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1777 * the bstr-wrapped CBOR is exited, the length is set back to the
1778 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001779 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001780 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001781 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001782 goto Done;
1783 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001784
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001785 /* Check to see if at the end of a bounded definite-length map or
1786 * array. The check for a break ending indefinite-length array is
1787 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001788 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001789 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001790 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001791 goto Done;
1792 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001793
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001794 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001795 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001796 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1797 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001798 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001799 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001801 /* Breaks ending arrays/maps are processed later in the call to
1802 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001803 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301804 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001805 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301806 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301807 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001808
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001809 /* Record the nesting level for this data item before processing
1810 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001811 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001812 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001813
Laurence Lundblade642282a2020-06-23 12:00:33 -07001814
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001815 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001816 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001817 /* If the new item is a map or array, descend.
1818 *
1819 * Empty indefinite-length maps and arrays are descended into,
1820 * but then ascended out of in the next chunk of code.
1821 *
1822 * Maps and arrays do count as items in the map/array that
1823 * encloses them so a decrement needs to be done for them too,
1824 * but that is done only when all the items in them have been
1825 * processed, not when they are opened with the exception of an
1826 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001827 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001828 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001829 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001830 pDecodedItem->uDataType,
1831 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001832 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001833 /* This error is probably a traversal error and it overrides
1834 * the non-traversal error.
1835 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001836 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001837 goto Done;
1838 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001839 }
1840
Laurence Lundblade02625d42020-06-25 14:41:41 -07001841 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1842 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1843 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001844 /* The following cases are handled here:
1845 * - A non-aggregate item like an integer or string
1846 * - An empty definite-length map or array
1847 * - An indefinite-length map or array that might be empty or might not.
1848 *
1849 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1850 * for an definite-length map/array and break detection for an
1851 * indefinite-0length map/array. If the end of the map/array was
1852 * reached, then it ascends nesting levels, possibly all the way
1853 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001854 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001855 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001856 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001857 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001858 /* This error is probably a traversal error and it overrides
1859 * the non-traversal error.
1860 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001861 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001862 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001863 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301864 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001865
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001866 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001867 /* Tell the caller what level is next. This tells them what
1868 * maps/arrays were closed out and makes it possible for them to
1869 * reconstruct the tree with just the information returned in a
1870 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001871 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001872 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001873 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001874 pDecodedItem->uNextNestLevel = 0;
1875 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001876 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001877 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001879Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001880 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001881}
1882
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001883
1884/**
1885 * @brief Shift 0th tag out of the tag list.
1886 *
1887 * pDecodedItem[in,out] The data item to convert.
1888 *
1889 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1890 * shifted into empty slot at the end of the tag list.
1891 */
1892static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001893{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001894 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1895 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1896 }
1897 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001898}
1899
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001900
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001901/**
1902 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1903 *
1904 * pDecodedItem[in,out] The data item to convert.
1905 *
1906 * @retval QCBOR_ERR_DATE_OVERFLOW
1907 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001908 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001909 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1910 *
1911 * The epoch date tag defined in QCBOR allows for floating-point
1912 * dates. It even allows a protocol to flop between date formats when
1913 * ever it wants. Floating-point dates aren't that useful as they are
1914 * only needed for dates beyond the age of the earth.
1915 *
1916 * This converts all the date formats into one format of an unsigned
1917 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001918 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001919static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001920{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001921 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001923#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001924 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001925#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001926
1927 switch (pDecodedItem->uDataType) {
1928
1929 case QCBOR_TYPE_INT64:
1930 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1931 break;
1932
1933 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001934 /* This only happens for CBOR type 0 > INT64_MAX so it is
1935 * always an overflow.
1936 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001937 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1938 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939 break;
1940
1941 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001942 case QCBOR_TYPE_FLOAT:
1943#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001944 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001945 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001946 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001947 pDecodedItem->val.dfnum :
1948 (double)pDecodedItem->val.fnum;
1949
1950 /* The conversion from float to integer requires overflow
1951 * detection since floats can be much larger than integers.
1952 * This implementation errors out on these large float values
1953 * since they are beyond the age of the earth.
1954 *
1955 * These constants for the overflow check are computed by the
1956 * compiler. They are not computed at run time.
1957 *
1958 * The factor of 0x7ff is added/subtracted to avoid a
1959 * rounding error in the wrong direction when the compiler
1960 * computes these constants. There is rounding because an
1961 * 64-bit integer has 63 bits of precision where a double
1962 * only has 53 bits. Without the 0x7ff factor, the compiler
1963 * may round up and produce a double for the bounds check
1964 * that is larger than can be stored in a 64-bit integer. The
1965 * amount of 0x7ff is picked because it has 11 bits set.
1966 *
1967 * Without the 0x7ff there is a ~30 minute range of time
1968 * values 10 billion years in the past and in the future
1969 * where this code could go wrong. Some compilers correctly
1970 * generate a warning or error without the 0x7ff.
1971 */
1972 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1973 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1974
1975 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001976 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001977 goto Done;
1978 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001979
1980 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001982 pDecodedItem->val.epochDate.fSecondsFraction =
1983 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001985#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001986
Laurence Lundbladec7114722020-08-13 05:11:40 -07001987 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001988 goto Done;
1989
Laurence Lundblade9682a532020-06-06 18:33:04 -07001990#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 break;
1992
1993 default:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001994 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001995 goto Done;
1996 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001997
Laurence Lundblade59289e52019-12-30 13:44:37 -08001998 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1999
2000Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002001 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002002}
2003
2004
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002005/**
2006 * @brief Convert the days epoch date.
2007 *
2008 * pDecodedItem[in,out] The data item to convert.
2009 *
2010 * @retval QCBOR_ERR_DATE_OVERFLOW
2011 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002012 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002013 * @retval QCBOR_ERR_BAD_TAG_CONTENT
2014 *
2015 * This is much simpler than the other epoch date format because
2016 * floating-porint is not allowed. This is mostly a simple type check.
2017 */
2018static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2019{
2020 QCBORError uReturn = QCBOR_SUCCESS;
2021
2022 switch (pDecodedItem->uDataType) {
2023
2024 case QCBOR_TYPE_INT64:
2025 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2026 break;
2027
2028 case QCBOR_TYPE_UINT64:
2029 /* This only happens for CBOR type 0 > INT64_MAX so it is
2030 * always an overflow.
2031 */
2032 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2033 goto Done;
2034 break;
2035
2036 default:
2037 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
2038 goto Done;
2039 break;
2040 }
2041
2042 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2043
2044Done:
2045 return uReturn;
2046}
2047
2048
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002049#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002050/**
2051 * @brief Decode decimal fractions and big floats.
2052 *
2053 * @param[in] pMe The decode context.
2054 * @param[in,out] pDecodedItem On input the array data item that
2055 * holds the mantissa and exponent. On
2056 * output the decoded mantissa and
2057 * exponent.
2058 *
2059 * @returns Decoding errors from getting primitive data items or
2060 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2061 *
2062 * When called pDecodedItem must be the array that is tagged as a big
2063 * float or decimal fraction, the array that has the two members, the
2064 * exponent and mantissa.
2065 *
2066 * This will fetch and decode the exponent and mantissa and put the
2067 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002068 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002069static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002070QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002071{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002072 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002074 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002075 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002076 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 goto Done;
2078 }
2079
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002080 /* A check for pDecodedItem->val.uCount == 2 would work for
2081 * definite-length arrays, but not for indefnite. Instead remember
2082 * the nesting level the two integers must be at, which is one
2083 * deeper than that of the array.
2084 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002085 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2086
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002087 /* --- Which is it, decimal fraction or a bigfloat? --- */
2088 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002089 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2090
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002091 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002093 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2094 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095 goto Done;
2096 }
2097 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002098 /* Array is empty or a map/array encountered when expecting an int */
2099 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100 goto Done;
2101 }
2102 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002103 /* Data arriving as an unsigned int < INT64_MAX has been
2104 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2105 * also means that the only data arriving here of type
2106 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2107 * and thus an error that will get handled in the next else.
2108 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002109 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2110 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002111 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2112 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002113 goto Done;
2114 }
2115
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002116 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002117 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002118 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2119 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002120 goto Done;
2121 }
2122 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002123 /* Mantissa missing or map/array encountered when expecting number */
2124 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002125 goto Done;
2126 }
2127 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002128 /* Data arriving as an unsigned int < INT64_MAX has been
2129 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2130 * also means that the only data arriving here of type
2131 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2132 * and thus an error that will get handled in an else below.
2133 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002134 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002135 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2136 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002137 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002138 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002139 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002140 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2141 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2142 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002143 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002144 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2145 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002146 goto Done;
2147 }
2148
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002149 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002150 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002151 /* Extra items in the decimal fraction / big float */
2152 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002153 goto Done;
2154 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002155 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002156
2157Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002158 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002159}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002160#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161
2162
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002163#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002164/**
2165 * @brief Decode the MIME type tag
2166 *
2167 * @param[in,out] pDecodedItem The item to decode.
2168 *
2169 * Handle the text and binary MIME type tags. Slightly too complicated
2170 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2171 * incorreclty text-only.
2172 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002173static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002174{
2175 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2176 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002177 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002178 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2179 } else {
2180 return QCBOR_ERR_BAD_OPT_TAG;
2181 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002182
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002183 return QCBOR_SUCCESS;
2184}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002185#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002186
2187
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002188/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002189 * Table of CBOR tags whose content is either a text string or a byte
2190 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2191 * of uQCBORtype indicates the content should be a byte string rather
2192 * than a text string
2193 */
2194struct StringTagMapEntry {
2195 uint16_t uTagNumber;
2196 uint8_t uQCBORtype;
2197};
2198
2199#define IS_BYTE_STRING_BIT 0x80
2200#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2201
2202static const struct StringTagMapEntry StringTagMap[] = {
2203 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002204 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002205 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2206 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2207 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2208 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002209#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002210 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2211 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2212 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2213 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002214#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002215 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2216 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2217};
2218
2219
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002220/**
2221 * @brief Process standard CBOR tags whose content is a string
2222 *
2223 * @param[in] uTag The tag.
2224 * @param[in,out] pDecodedItem The data item.
2225 *
2226 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2227 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2228 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2229 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002230 * Process the CBOR tags that whose content is a byte string or a text
2231 * string and for which the string is just passed on to the caller.
2232 *
2233 * This maps the CBOR tag to the QCBOR type and checks the content
2234 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002235 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002236 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002237 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002238static inline QCBORError
2239ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002240{
Laurence Lundblade99615302020-11-29 11:19:47 -08002241 /* This only works on tags that were not mapped; no need for other yet */
2242 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2243 return QCBOR_ERR_UNSUPPORTED;
2244 }
2245
2246 unsigned uIndex;
2247 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2248 if(StringTagMap[uIndex].uTagNumber == uTag) {
2249 break;
2250 }
2251 }
2252
2253 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2254 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002255 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002256 return QCBOR_ERR_UNSUPPORTED;
2257 }
2258
2259 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2260 if(uQCBORType & IS_BYTE_STRING_BIT) {
2261 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2262 }
2263
2264 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002265 return QCBOR_ERR_BAD_OPT_TAG;
2266 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002267
Laurence Lundblade99615302020-11-29 11:19:47 -08002268 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002269 return QCBOR_SUCCESS;
2270}
2271
2272
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002273/**
2274 * @brief Decode tag content for select tags (decoding layer 1).
2275 *
2276 * @param[in] pMe The decode context.
2277 * @param[out] pDecodedItem The decoded item.
2278 *
2279 * @return Decoding error code.
2280 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002281 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2282 * but the whole tag was not decoded. Here, the whole tags (tag number
2283 * and tag content) that are supported by QCBOR are decoded. This is a
2284 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002285 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002286static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002287QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002288{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002289 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002290
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002291 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002292 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002293 goto Done;
2294 }
2295
Laurence Lundblade99615302020-11-29 11:19:47 -08002296 /* When there are no tag numbers for the item, this exits first
2297 * thing and effectively does nothing.
2298 *
2299 * This loops over all the tag numbers accumulated for this item
2300 * trying to decode and interpret them. This stops at the end of
2301 * the list or at the first tag number that can't be interpreted by
2302 * this code. This is effectively a recursive processing of the
2303 * tags number list that handles nested tags.
2304 */
2305 while(1) {
2306 /* Don't bother to unmap tags via QCBORITem.uTags since this
2307 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2308 */
2309 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002310
Laurence Lundblade99615302020-11-29 11:19:47 -08002311 if(uTagToProcess == CBOR_TAG_INVALID16) {
2312 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002313 break;
2314
Laurence Lundblade99615302020-11-29 11:19:47 -08002315 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002316 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002317
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002318 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2319 uReturn = DecodeDaysEpoch(pDecodedItem);
2320
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002321#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002322 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2323 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002324 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002325#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002326#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002327 } else if(uTagToProcess == CBOR_TAG_MIME ||
2328 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002329 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002330#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002331
Laurence Lundblade99615302020-11-29 11:19:47 -08002332 } else {
2333 /* See if it is a pass-through byte/text string tag; process if so */
2334 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002335
Laurence Lundblade99615302020-11-29 11:19:47 -08002336 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2337 /* It wasn't a pass-through byte/text string tag so it is
2338 * an unknown tag. This is the exit from the loop on the
2339 * first unknown tag. It is a successful exit.
2340 */
2341 uReturn = QCBOR_SUCCESS;
2342 break;
2343 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002344 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002345
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002346 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002347 /* Error exit from the loop */
2348 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002349 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002350
2351 /* A tag was successfully processed, shift it out of the list of
2352 * tags returned. This is the loop increment.
2353 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002354 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002355 }
2356
2357Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002358 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002359}
2360
2361
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002362/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002363 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002364 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002365QCBORError
2366QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2367{
2368 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002369 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002370 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002371 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2372 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2373 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002374 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002375}
2376
2377
2378/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002379 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002380 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002381QCBORError
2382QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2383{
2384 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2385 const UsefulInputBuf Save = pMe->InBuf;
2386
2387 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2388
2389 pMe->nesting = SaveNesting;
2390 pMe->InBuf = Save;
2391
2392 return uErr;
2393}
2394
2395
2396/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002397 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002398 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002399void
2400QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2401{
2402 if(pMe->uLastError != QCBOR_SUCCESS) {
2403 return;
2404 }
2405
2406 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2407}
2408
2409
2410/*
2411 * Public function, see header qcbor/qcbor_decode.h file
2412 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002413void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2414{
2415 if(pMe->uLastError != QCBOR_SUCCESS) {
2416 return;
2417 }
2418
2419 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2420}
2421
2422
2423/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002424 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002425 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002426QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002427QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2428 QCBORItem *pDecodedItem,
2429 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002430{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002431 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002432
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002433 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2434 if(uReturn != QCBOR_SUCCESS) {
2435 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002436 }
2437
2438 if(pTags != NULL) {
2439 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002440 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002441 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2442 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002443 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002444 }
2445 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2446 return QCBOR_ERR_TOO_MANY_TAGS;
2447 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002448 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002449 pTags->uNumUsed++;
2450 }
2451 }
2452
2453 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002454}
2455
2456
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002457/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002458 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302459 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002460bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002461 const QCBORItem *pItem,
2462 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002463{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002464 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2465 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002466 break;
2467 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002468 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002469 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002470 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002471 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002472
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002473 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002474}
2475
2476
2477/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002478 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002479 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002480QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002481{
Laurence Lundblade87495732021-02-26 10:05:55 -07002482 if(puConsumed != NULL) {
2483 *puConsumed = pMe->InBuf.cursor;
2484 }
2485
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002486 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002487
2488 if(uReturn != QCBOR_SUCCESS) {
2489 goto Done;
2490 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002491
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002492 /* Error out if all the maps/arrays are not closed out */
2493 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002494 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002495 goto Done;
2496 }
2497
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002498 /* Error out if not all the bytes are consumed */
2499 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002500 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002501 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002502
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002503Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002504 return uReturn;
2505}
2506
2507
2508/*
2509 * Public function, see header qcbor/qcbor_decode.h file
2510 */
2511QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2512{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002513#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002514 /* Call the destructor for the string allocator if there is one.
2515 * Always called, even if there are errors; always have to clean up.
2516 */
2517 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002518#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002519
Laurence Lundblade87495732021-02-26 10:05:55 -07002520 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002521}
2522
2523
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002524/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002525 * Public function, see header qcbor/qcbor_decode.h file
2526 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002527// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002528uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2529 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002530 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002531{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002532 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2533 return CBOR_TAG_INVALID64;
2534 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002535 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2536 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002537 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002538 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002539 }
2540}
2541
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002542
Laurence Lundblade9b334962020-08-27 10:55:53 -07002543/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002544 * Public function, see header qcbor/qcbor_decode.h file
2545 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002546uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2547 uint32_t uIndex)
2548{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002549 if(pMe->uLastError != QCBOR_SUCCESS) {
2550 return CBOR_TAG_INVALID64;
2551 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002552 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2553 return CBOR_TAG_INVALID64;
2554 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002555 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002556 }
2557}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002558
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002559
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002560
2561
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002562#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002563
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002564/* ===========================================================================
2565 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002566
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002567 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002568 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2569 implements the function type QCBORStringAllocate and allows easy
2570 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002571
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002572 This particular allocator is built-in for convenience. The caller
2573 can implement their own. All of this following code will get
2574 dead-stripped if QCBORDecode_SetMemPool() is not called.
2575
2576 This is a very primitive memory allocator. It does not track
2577 individual allocations, only a high-water mark. A free or
2578 reallocation must be of the last chunk allocated.
2579
2580 The size of the pool and offset to free memory are packed into the
2581 first 8 bytes of the memory pool so we don't have to keep them in
2582 the decode context. Since the address of the pool may not be
2583 aligned, they have to be packed and unpacked as if they were
2584 serialized data of the wire or such.
2585
2586 The sizes packed in are uint32_t to be the same on all CPU types
2587 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002588 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002589
2590
Laurence Lundbladeee851742020-01-08 08:37:05 -08002591static inline int
2592MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002593{
2594 // Use of UsefulInputBuf is overkill, but it is convenient.
2595 UsefulInputBuf UIB;
2596
Laurence Lundbladeee851742020-01-08 08:37:05 -08002597 // Just assume the size here. It was checked during SetUp so
2598 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002599 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002600 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2601 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2602 return UsefulInputBuf_GetError(&UIB);
2603}
2604
2605
Laurence Lundbladeee851742020-01-08 08:37:05 -08002606static inline int
2607MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002608{
2609 // Use of UsefulOutBuf is overkill, but convenient. The
2610 // length check performed here is useful.
2611 UsefulOutBuf UOB;
2612
2613 UsefulOutBuf_Init(&UOB, Pool);
2614 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2615 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2616 return UsefulOutBuf_GetError(&UOB);
2617}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002618
2619
2620/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002621 Internal function for an allocation, reallocation free and destuct.
2622
2623 Having only one function rather than one each per mode saves space in
2624 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002625
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002626 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2627 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002628static UsefulBuf
2629MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002630{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002631 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002632
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002633 uint32_t uPoolSize;
2634 uint32_t uFreeOffset;
2635
2636 if(uNewSize > UINT32_MAX) {
2637 // This allocator is only good up to 4GB. This check should
2638 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2639 goto Done;
2640 }
2641 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2642
2643 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2644 goto Done;
2645 }
2646
2647 if(uNewSize) {
2648 if(pMem) {
2649 // REALLOCATION MODE
2650 // Calculate pointer to the end of the memory pool. It is
2651 // assumed that pPool + uPoolSize won't wrap around by
2652 // assuming the caller won't pass a pool buffer in that is
2653 // not in legitimate memory space.
2654 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2655
2656 // Check that the pointer for reallocation is in the range of the
2657 // pool. This also makes sure that pointer math further down
2658 // doesn't wrap under or over.
2659 if(pMem >= pPool && pMem < pPoolEnd) {
2660 // Offset to start of chunk for reallocation. This won't
2661 // wrap under because of check that pMem >= pPool. Cast
2662 // is safe because the pool is always less than UINT32_MAX
2663 // because of check in QCBORDecode_SetMemPool().
2664 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2665
2666 // Check to see if the allocation will fit. uPoolSize -
2667 // uMemOffset will not wrap under because of check that
2668 // pMem is in the range of the uPoolSize by check above.
2669 if(uNewSize <= uPoolSize - uMemOffset) {
2670 ReturnValue.ptr = pMem;
2671 ReturnValue.len = uNewSize;
2672
2673 // Addition won't wrap around over because uNewSize was
2674 // checked to be sure it is less than the pool size.
2675 uFreeOffset = uMemOffset + uNewSize32;
2676 }
2677 }
2678 } else {
2679 // ALLOCATION MODE
2680 // uPoolSize - uFreeOffset will not underflow because this
2681 // pool implementation makes sure uFreeOffset is always
2682 // smaller than uPoolSize through this check here and
2683 // reallocation case.
2684 if(uNewSize <= uPoolSize - uFreeOffset) {
2685 ReturnValue.len = uNewSize;
2686 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002687 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002688 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002689 }
2690 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002691 if(pMem) {
2692 // FREE MODE
2693 // Cast is safe because of limit on pool size in
2694 // QCBORDecode_SetMemPool()
2695 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2696 } else {
2697 // DESTRUCT MODE
2698 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002699 }
2700 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002701
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002702 UsefulBuf Pool = {pPool, uPoolSize};
2703 MemPool_Pack(Pool, uFreeOffset);
2704
2705Done:
2706 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002707}
2708
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002709
Laurence Lundbladef6531662018-12-04 10:42:22 +09002710/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002711 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002712 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002713QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2714 UsefulBuf Pool,
2715 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002716{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002717 // The pool size and free mem offset are packed into the beginning
2718 // of the pool memory. This compile time check make sure the
2719 // constant in the header is correct. This check should optimize
2720 // down to nothing.
2721 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002722 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002723 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002724
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002725 // The pool size and free offset packed in to the beginning of pool
2726 // memory are only 32-bits. This check will optimize out on 32-bit
2727 // machines.
2728 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002729 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002730 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002731
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002732 // This checks that the pool buffer given is big enough.
2733 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002734 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002735 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002736
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002737 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002738
Laurence Lundblade30816f22018-11-10 13:40:22 +07002739 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002740}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002741#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002742
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002743
2744
Laurence Lundblade9b334962020-08-27 10:55:53 -07002745static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2746{
2747 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2748}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002749
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002750
2751/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002752 Consume an entire map or array (and do next to
2753 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002754 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002755static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002756ConsumeItem(QCBORDecodeContext *pMe,
2757 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002758 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002760 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002761 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002762
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002763 // If it is a map or array, this will tell if it is empty.
2764 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2765
2766 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2767 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002768
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002769 /* This works for definite- and indefinite- length
Laurence Lundblade1341c592020-04-11 14:19:05 -07002770 * maps and arrays by using the nesting level
2771 */
2772 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002773 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002774 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002775 goto Done;
2776 }
2777 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002779 *puNextNestLevel = Item.uNextNestLevel;
2780
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002781 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002782
Laurence Lundblade1341c592020-04-11 14:19:05 -07002783 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002784 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002785 /* Just pass the nesting level through */
2786 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2787
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002788 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002789 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002790
2791Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002792 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002793}
2794
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002795
2796void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2797{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002798 QCBORDecode_VGetNext(pMe, pDecodedItem);
2799
2800 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002801 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2802 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002803 }
2804}
2805
2806
2807
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002808/* Call only on maps and arrays. Rewinds the cursor
2809 * to the start as if it was just entered.
2810 */
2811static void RewindMapOrArray(QCBORDecodeContext *pMe)
2812{
2813 /* Reset nesting tracking to the deepest bounded level */
2814 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2815
2816 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2817
2818 /* Reposition traversal cursor to the start of the map/array */
2819 UsefulInputBuf_Seek(&(pMe->InBuf),
2820 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2821}
2822
2823
2824/*
2825 Public function, see header qcbor/qcbor_decode.h file
2826 */
2827void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2828{
2829 if(pMe->nesting.pCurrentBounded != NULL) {
2830 /* In a bounded map, array or bstr-wrapped CBOR */
2831
2832 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2833 /* In bstr-wrapped CBOR. */
2834
2835 /* Reposition traversal cursor to start of wrapping byte string */
2836 UsefulInputBuf_Seek(&(pMe->InBuf),
2837 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2838 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2839
2840 } else {
2841 /* In a map or array */
2842 RewindMapOrArray(pMe);
2843 }
2844
2845 } else {
2846 /* Not in anything bounded */
2847
2848 /* Reposition traversal cursor to the start of input CBOR */
2849 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2850
2851 /* Reset nesting tracking to beginning of input. */
2852 DecodeNesting_Init(&(pMe->nesting));
2853 }
2854
2855 pMe->uLastError = QCBOR_SUCCESS;
2856}
2857
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002858
Laurence Lundblade1341c592020-04-11 14:19:05 -07002859/* Return true if the labels in Item1 and Item2 are the same.
2860 Works only for integer and string labels. Returns false
2861 for any other type. */
2862static inline bool
2863MatchLabel(QCBORItem Item1, QCBORItem Item2)
2864{
2865 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2866 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2867 return true;
2868 }
2869 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002870 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002871 return true;
2872 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002873 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002874 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2875 return true;
2876 }
2877 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2878 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2879 return true;
2880 }
2881 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002882
Laurence Lundblade1341c592020-04-11 14:19:05 -07002883 /* Other label types are never matched */
2884 return false;
2885}
2886
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002887
2888/*
2889 Returns true if Item1 and Item2 are the same type
2890 or if either are of QCBOR_TYPE_ANY.
2891 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002892static inline bool
2893MatchType(QCBORItem Item1, QCBORItem Item2)
2894{
2895 if(Item1.uDataType == Item2.uDataType) {
2896 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002897 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002898 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002899 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002900 return true;
2901 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002902 return false;
2903}
2904
2905
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002906/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002907 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002908
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002909 @param[in] pMe The decode context to search.
2910 @param[in,out] pItemArray The items to search for and the items found.
2911 @param[out] puOffset Byte offset of last item matched.
2912 @param[in] pCBContext Context for the not-found item call back.
2913 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002914
2915 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2916
Laurence Lundblade93d89472020-10-03 22:30:50 -07002917 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2918 were found for one of the labels being
2919 search for. This duplicate detection is
2920 only performed for items in pItemArray,
2921 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002922
Laurence Lundblade93d89472020-10-03 22:30:50 -07002923 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2924 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002925
2926 @retval Also errors returned by QCBORDecode_GetNext().
2927
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002928 On input pItemArray contains a list of labels and data types
2929 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002930
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002931 On output the fully retrieved items are filled in with
2932 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002933
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002934 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002935
2936 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002937 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002938static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002939MapSearch(QCBORDecodeContext *pMe,
2940 QCBORItem *pItemArray,
2941 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002942 void *pCBContext,
2943 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002944{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002945 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002946 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002947
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002948 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002949 uReturn = pMe->uLastError;
2950 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002951 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002952
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002953 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002954 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2955 /* QCBOR_TYPE_NONE as first item indicates just looking
2956 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002957 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2958 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002959 }
2960
Laurence Lundblade085d7952020-07-24 10:26:30 -07002961 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2962 // It is an empty bounded array or map
2963 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2964 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002965 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002966 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002967 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002968 // Nothing is ever found in an empty array or map. All items
2969 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002970 uReturn = QCBOR_SUCCESS;
2971 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002972 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002973 }
2974
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002975 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002976 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2977
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002978 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002979 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002980
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002981 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002982 Loop over all the items in the map or array. Each item
2983 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002984 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002985 length maps and arrays. The only reason this is ever
2986 called on arrays is to find their end position.
2987
2988 This will always run over all items in order to do
2989 duplicate detection.
2990
2991 This will exit with failure if it encounters an
2992 unrecoverable error, but continue on for recoverable
2993 errors.
2994
2995 If a recoverable error occurs on a matched item, then
2996 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002997 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002998 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002999 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003000 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003001 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003002 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003003
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003004 /* Get the item */
3005 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003006 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003007 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003008 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003009 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003010 goto Done;
3011 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003012 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003013 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003014 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003015 goto Done;
3016 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003017
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003018 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003019 bool bMatched = false;
3020 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3021 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003022 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003023 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3024 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003025 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003026 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003027 if(uResult != QCBOR_SUCCESS) {
3028 /* The label matches, but the data item is in error */
3029 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003030 goto Done;
3031 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003032 if(!MatchType(Item, pItemArray[nIndex])) {
3033 /* The data item is not of the type(s) requested */
3034 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003035 goto Done;
3036 }
3037
Laurence Lundblade1341c592020-04-11 14:19:05 -07003038 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003039 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003040 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003041 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003042 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003043 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003044 bMatched = true;
3045 }
3046 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003047
3048
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003049 if(!bMatched && pfCallback != NULL) {
3050 /*
3051 Call the callback on unmatched labels.
3052 (It is tempting to do duplicate detection here, but that would
3053 require dynamic memory allocation because the number of labels
3054 that might be encountered is unbounded.)
3055 */
3056 uReturn = (*pfCallback)(pCBContext, &Item);
3057 if(uReturn != QCBOR_SUCCESS) {
3058 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003059 }
3060 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003061
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003062 /*
3063 Consume the item whether matched or not. This
3064 does the work of traversing maps and array and
3065 everything in them. In this loop only the
3066 items at the current nesting level are examined
3067 to match the labels.
3068 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003069 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003070 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003071 goto Done;
3072 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003073
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003074 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003075
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003076 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003077
3078 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003079
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003080 // Check here makes sure that this won't accidentally be
3081 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003082 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003083 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3084 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003085 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3086 goto Done;
3087 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003088 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3089 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003090
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003091 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003092 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3093
3094 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003095 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003096 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003097 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003098 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3099 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003100 }
3101 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003102
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003103 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003104}
3105
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003106
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003107/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003108 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003109*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003110void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3111 int64_t nLabel,
3112 uint8_t uQcborType,
3113 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003114{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003115 if(pMe->uLastError != QCBOR_SUCCESS) {
3116 return;
3117 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003118
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003119 QCBORItem OneItemSeach[2];
3120 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3121 OneItemSeach[0].label.int64 = nLabel;
3122 OneItemSeach[0].uDataType = uQcborType;
3123 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003124
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003125 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003126
3127 *pItem = OneItemSeach[0];
3128
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003129 if(uReturn != QCBOR_SUCCESS) {
3130 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003131 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003132 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003133 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003134 }
3135
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003136 Done:
3137 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003138}
3139
3140
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003141/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003142 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003143*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003144void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3145 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003146 uint8_t uQcborType,
3147 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003148{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003149 if(pMe->uLastError != QCBOR_SUCCESS) {
3150 return;
3151 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003152
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003153 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003154 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3155 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3156 OneItemSeach[0].uDataType = uQcborType;
3157 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003158
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003159 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3160 if(uReturn != QCBOR_SUCCESS) {
3161 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003162 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003163 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003164 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003165 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003166 }
3167
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003168 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003169
3170Done:
3171 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003172}
3173
3174
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003175
Laurence Lundblade93d89472020-10-03 22:30:50 -07003176static QCBORError
3177CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003178{
3179 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3180 if(uDataType == puTypeList[i]) {
3181 return QCBOR_SUCCESS;
3182 }
3183 }
3184 return QCBOR_ERR_UNEXPECTED_TYPE;
3185}
3186
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003187
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003188/**
3189 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003190 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003191
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003192 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3193 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003194
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003195 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3196 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003197 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003198static QCBORError
3199CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003200{
3201 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3202 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3203 /* There are tags that QCBOR couldn't process on this item and
3204 the caller has told us there should not be. */
3205 return QCBOR_ERR_UNEXPECTED_TYPE;
3206 }
3207
3208 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3209 const int nItemType = pItem->uDataType;
3210
3211 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3212 // Must match the tag and only the tag
3213 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3214 }
3215
3216 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3217 if(uReturn == QCBOR_SUCCESS) {
3218 return QCBOR_SUCCESS;
3219 }
3220
3221 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3222 /* Must match the content type and only the content type.
3223 There was no match just above so it is a fail. */
3224 return QCBOR_ERR_UNEXPECTED_TYPE;
3225 }
3226
3227 /* If here it can match either the tag or the content
3228 and it hasn't matched the content, so the end
3229 result is whether it matches the tag. This is
3230 also the case that the CBOR standard discourages. */
3231
3232 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3233}
3234
Laurence Lundblade9b334962020-08-27 10:55:53 -07003235
Laurence Lundblade9b334962020-08-27 10:55:53 -07003236
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003237// This could be semi-private if need be
3238static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003239void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3240 int64_t nLabel,
3241 TagSpecification TagSpec,
3242 QCBORItem *pItem)
3243{
3244 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3245 if(pMe->uLastError != QCBOR_SUCCESS) {
3246 return;
3247 }
3248
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003249 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003250}
3251
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003252
3253// This could be semi-private if need be
3254static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003255void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3256 const char *szLabel,
3257 TagSpecification TagSpec,
3258 QCBORItem *pItem)
3259{
3260 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3261 if(pMe->uLastError != QCBOR_SUCCESS) {
3262 return;
3263 }
3264
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003265 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003266}
3267
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003268// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003269void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3270 int64_t nLabel,
3271 TagSpecification TagSpec,
3272 UsefulBufC *pString)
3273{
3274 QCBORItem Item;
3275 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3276 if(pMe->uLastError == QCBOR_SUCCESS) {
3277 *pString = Item.val.string;
3278 }
3279}
3280
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003281// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003282void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3283 const char * szLabel,
3284 TagSpecification TagSpec,
3285 UsefulBufC *pString)
3286{
3287 QCBORItem Item;
3288 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3289 if(pMe->uLastError == QCBOR_SUCCESS) {
3290 *pString = Item.val.string;
3291 }
3292}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003293
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003294/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003295 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003296*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003297void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003298{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003299 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3300 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003301}
3302
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003303/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003304 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003305*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003306void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3307 QCBORItem *pItemList,
3308 void *pCallbackCtx,
3309 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003310{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003311 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3312 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003313}
3314
3315
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003316/**
3317 * @brief Search for a map/array by label and enter it
3318 *
3319 * @param[in] pMe The decode context.
3320 * @param[in] pSearch The map/array to search for.
3321 *
3322 * @c pSearch is expected to contain one item of type map or array
3323 * with the label specified. The current bounded map will be searched for
3324 * this and if found will be entered.
3325 *
3326 * If the label is not found, or the item found is not a map or array,
3327 * the error state is set.
3328 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003329static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003330{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003331 // The first item in pSearch is the one that is to be
3332 // entered. It should be the only one filled in. Any other
3333 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003334 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003335 return;
3336 }
3337
3338 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003339 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003340 if(pMe->uLastError != QCBOR_SUCCESS) {
3341 return;
3342 }
3343
Laurence Lundblade9b334962020-08-27 10:55:53 -07003344 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003345 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003346 return;
3347 }
3348
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003349
3350 /* The map or array was found. Now enter it.
3351 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003352 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3353 * next item for the pre-order traversal cursor to be the map/array
3354 * found by MapSearch(). The next few lines of code force the
3355 * cursor to that.
3356 *
3357 * There is no need to retain the old cursor because
3358 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3359 * beginning of the map/array being entered.
3360 *
3361 * The cursor is forced by: 1) setting the input buffer position to
3362 * the item offset found by MapSearch(), 2) setting the map/array
3363 * counter to the total in the map/array, 3) setting the nesting
3364 * level. Setting the map/array counter to the total is not
3365 * strictly correct, but this is OK because this cursor only needs
3366 * to be used to get one item and MapSearch() has already found it
3367 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003368 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003369 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003370
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003371 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3372
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003373 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003374
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003375 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003376}
3377
3378
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003379/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003380 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003381*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003382void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003383{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003384 QCBORItem OneItemSeach[2];
3385 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3386 OneItemSeach[0].label.int64 = nLabel;
3387 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3388 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003389
Laurence Lundblade9b334962020-08-27 10:55:53 -07003390 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003391 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003392}
3393
3394
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003395/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003396 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003397*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003398void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003399{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003400 QCBORItem OneItemSeach[2];
3401 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3402 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3403 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3404 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003405
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003406 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003407}
3408
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003409/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003410 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003411*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003412void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003413{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003414 QCBORItem OneItemSeach[2];
3415 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3416 OneItemSeach[0].label.int64 = nLabel;
3417 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3418 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003419
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003420 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003421}
3422
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003423/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003424 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003425*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003426void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3427{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003428 QCBORItem OneItemSeach[2];
3429 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3430 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3431 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3432 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003433
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003434 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003435}
3436
3437
Laurence Lundblade02625d42020-06-25 14:41:41 -07003438// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003439void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003440{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003441 QCBORError uErr;
3442
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003443 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003444 if(pMe->uLastError != QCBOR_SUCCESS) {
3445 // Already in error state; do nothing.
3446 return;
3447 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003448
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003449 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003450 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003451 uErr = QCBORDecode_GetNext(pMe, &Item);
3452 if(uErr != QCBOR_SUCCESS) {
3453 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003454 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003455 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003456 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3457 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003458 }
3459
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003460 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003461
3462
Laurence Lundbladef0499502020-08-01 11:55:57 -07003463 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003464 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003465 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3466 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003467 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003468 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3469 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003470 // Special case to increment nesting level for zero-length maps
3471 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003472 DecodeNesting_Descend(&(pMe->nesting), uType);
3473 }
3474
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003475 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003476
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003477 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3478 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003479
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003480 if(pItem != NULL) {
3481 *pItem = Item;
3482 }
3483
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003484Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003485 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003486}
3487
Laurence Lundblade02625d42020-06-25 14:41:41 -07003488
3489/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003490 This is the common work for exiting a level that is a bounded map,
3491 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003492
3493 One chunk of work is to set up the pre-order traversal so it is at
3494 the item just after the bounded map, array or bstr that is being
3495 exited. This is somewhat complex.
3496
3497 The other work is to level-up the bounded mode to next higest bounded
3498 mode or the top level if there isn't one.
3499 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003500static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003501ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003502{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003503 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003504
Laurence Lundblade02625d42020-06-25 14:41:41 -07003505 /*
3506 First the pre-order-traversal byte offset is positioned to the
3507 item just after the bounded mode item that was just consumed.
3508 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003509 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3510
Laurence Lundblade02625d42020-06-25 14:41:41 -07003511 /*
3512 Next, set the current nesting level to one above the bounded level
3513 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003514
Laurence Lundblade02625d42020-06-25 14:41:41 -07003515 DecodeNesting_CheckBoundedType() is always called before this and
3516 makes sure pCurrentBounded is valid.
3517 */
3518 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3519
3520 /*
3521 This does the complex work of leveling up the pre-order traversal
3522 when the end of a map or array or another bounded level is
3523 reached. It may do nothing, or ascend all the way to the top
3524 level.
3525 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003526 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003527 if(uErr != QCBOR_SUCCESS) {
3528 goto Done;
3529 }
3530
Laurence Lundblade02625d42020-06-25 14:41:41 -07003531 /*
3532 This makes the next highest bounded level the current bounded
3533 level. If there is no next highest level, then no bounded mode is
3534 in effect.
3535 */
3536 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003537
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003538 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003539
3540Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003541 return uErr;
3542}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003543
Laurence Lundblade02625d42020-06-25 14:41:41 -07003544
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003545// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003546void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003547{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003548 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003549 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003550 return;
3551 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003552
Laurence Lundblade02625d42020-06-25 14:41:41 -07003553 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003554
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003555 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003556 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003557 goto Done;
3558 }
3559
Laurence Lundblade02625d42020-06-25 14:41:41 -07003560 /*
3561 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003562 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003563 from previous map search, then do a dummy search.
3564 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003565 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003566 QCBORItem Dummy;
3567 Dummy.uLabelType = QCBOR_TYPE_NONE;
3568 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3569 if(uErr != QCBOR_SUCCESS) {
3570 goto Done;
3571 }
3572 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003573
Laurence Lundblade02625d42020-06-25 14:41:41 -07003574 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003575
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003576Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003577 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003578}
3579
3580
Laurence Lundblade1341c592020-04-11 14:19:05 -07003581
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003582static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003583 const QCBORItem *pItem,
3584 uint8_t uTagRequirement,
3585 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003586{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003587 if(pBstr) {
3588 *pBstr = NULLUsefulBufC;
3589 }
3590
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003591 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003592 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003593 return pMe->uLastError;
3594 }
3595
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003596 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003597
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003598 const TagSpecification TagSpec =
3599 {
3600 uTagRequirement,
3601 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3602 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3603 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003604
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003605 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003606 if(uError != QCBOR_SUCCESS) {
3607 goto Done;
3608 }
3609
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003610 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003611 /* Reverse the decrement done by GetNext() for the bstr so the
3612 * increment in QCBORDecode_NestLevelAscender() called by
3613 * ExitBoundedLevel() will work right.
3614 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003615 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003616 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003617
3618 if(pBstr) {
3619 *pBstr = pItem->val.string;
3620 }
3621
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003622 /* This saves the current length of the UsefulInputBuf and then
3623 * narrows the UsefulInputBuf to start and length of the wrapped
3624 * CBOR that is being entered.
3625 *
3626 * Most of these calls are simple inline accessors so this doesn't
3627 * amount to much code.
3628 */
3629
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003630 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003631 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3632 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003633 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003634 goto Done;
3635 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003636
3637 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3638 pItem->val.string.ptr);
3639 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3640 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3641 /* This should never happen because pItem->val.string.ptr should
3642 * always be valid since it was just returned.
3643 */
3644 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3645 goto Done;
3646 }
3647
3648 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3649
3650 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003651 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003652
Laurence Lundblade02625d42020-06-25 14:41:41 -07003653 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003654 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003655 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003656Done:
3657 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003658}
3659
3660
Laurence Lundblade02625d42020-06-25 14:41:41 -07003661/*
3662 Public function, see header qcbor/qcbor_decode.h file
3663 */
3664void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003665 uint8_t uTagRequirement,
3666 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003667{
3668 if(pMe->uLastError != QCBOR_SUCCESS) {
3669 // Already in error state; do nothing.
3670 return;
3671 }
3672
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003673 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003674 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003675 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3676 if(pMe->uLastError != QCBOR_SUCCESS) {
3677 return;
3678 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003679
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003680 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003681 &Item,
3682 uTagRequirement,
3683 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003684}
3685
3686
Laurence Lundblade02625d42020-06-25 14:41:41 -07003687/*
3688 Public function, see header qcbor/qcbor_decode.h file
3689 */
3690void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003691 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003692 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003693 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003694{
3695 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003696 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003697
Laurence Lundblade93d89472020-10-03 22:30:50 -07003698 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3699 &Item,
3700 uTagRequirement,
3701 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003702}
3703
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003704
Laurence Lundblade02625d42020-06-25 14:41:41 -07003705/*
3706 Public function, see header qcbor/qcbor_decode.h file
3707 */
3708void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003709 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003710 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003711 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003712{
3713 QCBORItem Item;
3714 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3715
Laurence Lundblade93d89472020-10-03 22:30:50 -07003716 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3717 &Item,
3718 uTagRequirement,
3719 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003720}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003721
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003722
Laurence Lundblade02625d42020-06-25 14:41:41 -07003723/*
3724 Public function, see header qcbor/qcbor_decode.h file
3725 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003726void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003727{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003728 if(pMe->uLastError != QCBOR_SUCCESS) {
3729 // Already in error state; do nothing.
3730 return;
3731 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003732
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003733 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003734 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003735 return;
3736 }
3737
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003738 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3739
Laurence Lundblade02625d42020-06-25 14:41:41 -07003740 /*
3741 Reset the length of the UsefulInputBuf to what it was before
3742 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003743 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003744 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003745 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003746
3747
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003748 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003749 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003750}
3751
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003752
Laurence Lundbladee6430642020-03-14 21:15:44 -07003753
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003754
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003755static inline void
3756ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003757{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003758 if(pMe->uLastError != QCBOR_SUCCESS) {
3759 /* Already in error state, do nothing */
3760 return;
3761 }
3762
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003763 switch(pItem->uDataType) {
3764 case QCBOR_TYPE_TRUE:
3765 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003766 break;
3767
3768 case QCBOR_TYPE_FALSE:
3769 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003770 break;
3771
3772 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003773 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003774 break;
3775 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003776 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003777}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003778
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003779
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003780/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003781 * Public function, see header qcbor/qcbor_decode.h file
3782 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003784{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003785 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003786 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003787 return;
3788 }
3789
Laurence Lundbladec4537442020-04-14 18:53:22 -07003790 QCBORItem Item;
3791
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003792 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3793
3794 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003795}
3796
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003797
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003798/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003799 * Public function, see header qcbor/qcbor_decode.h file
3800 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003801void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003802{
3803 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003804 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003805
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003806 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003807}
3808
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003809
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003810/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003811 * Public function, see header qcbor/qcbor_decode.h file
3812 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003813void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3814{
3815 QCBORItem Item;
3816 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3817
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003818 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003819}
3820
3821
3822
Laurence Lundbladec7114722020-08-13 05:11:40 -07003823
3824static void ProcessEpochDate(QCBORDecodeContext *pMe,
3825 QCBORItem *pItem,
3826 uint8_t uTagRequirement,
3827 int64_t *pnTime)
3828{
3829 if(pMe->uLastError != QCBOR_SUCCESS) {
3830 // Already in error state, do nothing
3831 return;
3832 }
3833
3834 QCBORError uErr;
3835
3836 const TagSpecification TagSpec =
3837 {
3838 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003839 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3840 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003841 };
3842
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003843 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003844 if(uErr != QCBOR_SUCCESS) {
3845 goto Done;
3846 }
3847
3848 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3849 uErr = DecodeDateEpoch(pItem);
3850 if(uErr != QCBOR_SUCCESS) {
3851 goto Done;
3852 }
3853 }
3854
Laurence Lundblade9b334962020-08-27 10:55:53 -07003855 // Save the tags in the last item's tags in the decode context
3856 // for QCBORDecode_GetNthTagOfLast()
3857 CopyTags(pMe, pItem);
3858
Laurence Lundbladec7114722020-08-13 05:11:40 -07003859 *pnTime = pItem->val.epochDate.nSeconds;
3860
3861Done:
3862 pMe->uLastError = (uint8_t)uErr;
3863}
3864
3865
3866void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003867 uint8_t uTagRequirement,
3868 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003869{
3870 if(pMe->uLastError != QCBOR_SUCCESS) {
3871 // Already in error state, do nothing
3872 return;
3873 }
3874
3875 QCBORItem Item;
3876 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3877
3878 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3879}
3880
3881
3882void
3883QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3884 int64_t nLabel,
3885 uint8_t uTagRequirement,
3886 int64_t *pnTime)
3887{
3888 QCBORItem Item;
3889 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3890 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3891}
3892
3893
3894void
3895QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3896 const char *szLabel,
3897 uint8_t uTagRequirement,
3898 int64_t *pnTime)
3899{
3900 QCBORItem Item;
3901 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3902 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3903}
3904
3905
3906
Laurence Lundblade46d63e92021-05-13 11:37:10 -07003907/*
3908 * Common processing for the RFC 8943 day-count tag. Mostly
3909 * make sure the tag content is correct and copy forward any
3910 * further other tag numbers.
3911 */
3912static void ProcessEpochDays(QCBORDecodeContext *pMe,
3913 QCBORItem *pItem,
3914 uint8_t uTagRequirement,
3915 int64_t *pnDays)
3916{
3917 if(pMe->uLastError != QCBOR_SUCCESS) {
3918 /* Already in error state, do nothing */
3919 return;
3920 }
3921
3922 QCBORError uErr;
3923
3924 const TagSpecification TagSpec =
3925 {
3926 uTagRequirement,
3927 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3928 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3929 };
3930
3931 uErr = CheckTagRequirement(TagSpec, pItem);
3932 if(uErr != QCBOR_SUCCESS) {
3933 goto Done;
3934 }
3935
3936 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
3937 uErr = DecodeDaysEpoch(pItem);
3938 if(uErr != QCBOR_SUCCESS) {
3939 goto Done;
3940 }
3941 }
3942
3943 /* Save the tags in the last item's tags in the decode context
3944 * for QCBORDecode_GetNthTagOfLast()
3945 */
3946 CopyTags(pMe, pItem);
3947
3948 *pnDays = pItem->val.epochDays;
3949
3950Done:
3951 pMe->uLastError = (uint8_t)uErr;
3952}
3953
3954
3955/*
3956 * Public function, see header qcbor/qcbor_decode.h
3957 */
3958void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
3959 uint8_t uTagRequirement,
3960 int64_t *pnDays)
3961{
3962 if(pMe->uLastError != QCBOR_SUCCESS) {
3963 /* Already in error state, do nothing */
3964 return;
3965 }
3966
3967 QCBORItem Item;
3968 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3969
3970 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
3971}
3972
3973
3974/*
3975 * Public function, see header qcbor/qcbor_decode.h
3976 */
3977void
3978QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
3979 int64_t nLabel,
3980 uint8_t uTagRequirement,
3981 int64_t *pnDays)
3982{
3983 QCBORItem Item;
3984 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3985 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
3986}
3987
3988
3989/*
3990 * Public function, see header qcbor/qcbor_decode.h
3991 */
3992void
3993QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
3994 const char *szLabel,
3995 uint8_t uTagRequirement,
3996 int64_t *pnDays)
3997{
3998 QCBORItem Item;
3999 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4000 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4001}
4002
4003
4004
Laurence Lundbladec7114722020-08-13 05:11:40 -07004005
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004006void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4007 TagSpecification TagSpec,
4008 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004009{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004010 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004011 // Already in error state, do nothing
4012 return;
4013 }
4014
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004015 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004016 QCBORItem Item;
4017
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004018 uError = QCBORDecode_GetNext(pMe, &Item);
4019 if(uError != QCBOR_SUCCESS) {
4020 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004021 return;
4022 }
4023
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004024 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004025
4026 if(pMe->uLastError == QCBOR_SUCCESS) {
4027 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004028 } else {
4029 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004030 }
4031}
4032
Laurence Lundbladec4537442020-04-14 18:53:22 -07004033
4034
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004036static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004037 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004038 UsefulBufC *pValue,
4039 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004040{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004041 const TagSpecification TagSpec =
4042 {
4043 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004044 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4045 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004046 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004048 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004049 if(uErr != QCBOR_SUCCESS) {
4050 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004052
4053 *pValue = pItem->val.string;
4054
4055 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4056 *pbIsNegative = false;
4057 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4058 *pbIsNegative = true;
4059 }
4060
4061 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004062}
4063
4064
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004065/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004066 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004067 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004068void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4069 uint8_t uTagRequirement,
4070 UsefulBufC *pValue,
4071 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004072{
4073 if(pMe->uLastError != QCBOR_SUCCESS) {
4074 // Already in error state, do nothing
4075 return;
4076 }
4077
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004078 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004079 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4080 if(uError != QCBOR_SUCCESS) {
4081 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004082 return;
4083 }
4084
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004085 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004086}
4087
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004088
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004089/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004090 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004091*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004092void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4093 int64_t nLabel,
4094 uint8_t uTagRequirement,
4095 UsefulBufC *pValue,
4096 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004097{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004098 QCBORItem Item;
4099 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004100 if(pMe->uLastError != QCBOR_SUCCESS) {
4101 return;
4102 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004103
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004104 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004105}
4106
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004107
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004108/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004109 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004110*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004111void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4112 const char *szLabel,
4113 uint8_t uTagRequirement,
4114 UsefulBufC *pValue,
4115 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004116{
4117 QCBORItem Item;
4118 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004119 if(pMe->uLastError != QCBOR_SUCCESS) {
4120 return;
4121 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004122
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004123 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004124}
4125
4126
4127
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004128
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004129// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004130QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
4131 const QCBORItem *pItem,
4132 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07004133 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004134{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004135 const TagSpecification TagSpecText =
4136 {
4137 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004138 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4139 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004140 };
4141 const TagSpecification TagSpecBinary =
4142 {
4143 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004144 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4145 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004146 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004147
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004148 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004149
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004150 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004151 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004152 if(pbIsTag257 != NULL) {
4153 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004154 }
4155 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004156 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004157 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004158 if(pbIsTag257 != NULL) {
4159 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004160 }
4161 uReturn = QCBOR_SUCCESS;
4162
4163 } else {
4164 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4165 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004166
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004167 return uReturn;
4168}
4169
Laurence Lundblade93d89472020-10-03 22:30:50 -07004170// Improvement: add methods for wrapped CBOR, a simple alternate
4171// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004172
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004173
4174
4175
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004176#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004177
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004178typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004179
4180
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004181// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004182static QCBORError
4183Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004184{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004185 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004186
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004187 if(uResult != 0) {
4188 /* This loop will run a maximum of 19 times because
4189 * UINT64_MAX < 10 ^^ 19. More than that will cause
4190 * exit with the overflow error
4191 */
4192 for(; nExponent > 0; nExponent--) {
4193 if(uResult > UINT64_MAX / 10) {
4194 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4195 }
4196 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004197 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004198
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004199 for(; nExponent < 0; nExponent++) {
4200 uResult = uResult / 10;
4201 if(uResult == 0) {
4202 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4203 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004204 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004205 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004206 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004207
4208 *puResult = uResult;
4209
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004210 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004211}
4212
4213
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004214// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004215static QCBORError
4216Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004217{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004218 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004219
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004220 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004221
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004222 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004223 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004224 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004225 */
4226 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004227 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004228 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004229 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004230 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004231 nExponent--;
4232 }
4233
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004234 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004235 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004236 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4237 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004238 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004239 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004240 }
4241
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004242 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004243
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004244 return QCBOR_SUCCESS;
4245}
4246
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004247
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004248/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004249 Compute value with signed mantissa and signed result. Works with
4250 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004251 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004252static inline QCBORError ExponentiateNN(int64_t nMantissa,
4253 int64_t nExponent,
4254 int64_t *pnResult,
4255 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004256{
4257 uint64_t uResult;
4258
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004259 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004260 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004261 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4262
4263 // Do the exponentiation of the positive mantissa
4264 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4265 if(uReturn) {
4266 return uReturn;
4267 }
4268
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004269
Laurence Lundblade983500d2020-05-14 11:49:34 -07004270 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4271 of INT64_MIN. This assumes two's compliment representation where
4272 INT64_MIN is one increment farther from 0 than INT64_MAX.
4273 Trying to write -INT64_MIN doesn't work to get this because the
4274 compiler tries to work with an int64_t which can't represent
4275 -INT64_MIN.
4276 */
4277 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4278
4279 // Error out if too large
4280 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004281 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4282 }
4283
4284 // Casts are safe because of checks above
4285 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4286
4287 return QCBOR_SUCCESS;
4288}
4289
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004290
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004291/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004292 Compute value with signed mantissa and unsigned result. Works with
4293 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004294 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004295static inline QCBORError ExponentitateNU(int64_t nMantissa,
4296 int64_t nExponent,
4297 uint64_t *puResult,
4298 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004299{
4300 if(nMantissa < 0) {
4301 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4302 }
4303
4304 // Cast to unsigned is OK because of check for negative
4305 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4306 // Exponentiation is straight forward
4307 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4308}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004309
4310
4311/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004312 Compute value with signed mantissa and unsigned result. Works with
4313 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314 */
4315static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4316 int64_t nExponent,
4317 uint64_t *puResult,
4318 fExponentiator pfExp)
4319{
4320 return (*pfExp)(uMantissa, nExponent, puResult);
4321}
4322
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004323#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004324
4325
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004326
4327
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004328
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004329static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004330{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004331 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004332
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004333 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004334 const uint8_t *pByte = BigNum.ptr;
4335 size_t uLen = BigNum.len;
4336 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004337 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004338 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004339 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004340 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004341 }
4342
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004343 *pResult = uResult;
4344 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004345}
4346
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004347
Laurence Lundblade887add82020-05-17 05:50:34 -07004348static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004349{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004350 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004351}
4352
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004353
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004354static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004355{
4356 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004357 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4358 if(uError) {
4359 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004360 }
4361 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4362 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004363 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004364}
4365
4366
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004367static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004368{
4369 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004370 /* The negative integer furthest from zero for a C int64_t is
4371 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4372 negative number in CBOR is computed as -n - 1 where n is the
4373 encoded integer, where n is what is in the variable BigNum. When
4374 converting BigNum to a uint64_t, the maximum value is thus
4375 INT64_MAX, so that when it -n - 1 is applied to it the result will
4376 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004377
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004378 -n - 1 <= INT64_MIN.
4379 -n - 1 <= -INT64_MAX - 1
4380 n <= INT64_MAX.
4381 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004382 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004383 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004384 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004385 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004386
4387 /// Now apply -n - 1. The cast is safe because
4388 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4389 // is the largest positive integer that an int64_t can
4390 // represent. */
4391 *pnResult = -(int64_t)uResult - 1;
4392
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004393 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004394}
4395
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004396
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004397
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004398
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004399
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004401Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004403\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004404
Laurence Lundblade93d89472020-10-03 22:30:50 -07004405\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4406 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407
4408\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4409
Laurence Lundblade93d89472020-10-03 22:30:50 -07004410\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4411 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004412*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004413static QCBORError
4414ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004415{
4416 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004417 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004418 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004419#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004420 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004421 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4422 http://www.cplusplus.com/reference/cmath/llround/
4423 */
4424 // Not interested in FE_INEXACT
4425 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004426 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4427 *pnValue = llround(pItem->val.dfnum);
4428 } else {
4429 *pnValue = lroundf(pItem->val.fnum);
4430 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004431 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4432 // llround() shouldn't result in divide by zero, but catch
4433 // it here in case it unexpectedly does. Don't try to
4434 // distinguish between the various exceptions because it seems
4435 // they vary by CPU, compiler and OS.
4436 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004437 }
4438 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004440 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004441#else
4442 return QCBOR_ERR_HW_FLOAT_DISABLED;
4443#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004444 break;
4445
4446 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004447 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004448 *pnValue = pItem->val.int64;
4449 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004450 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004451 }
4452 break;
4453
4454 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004456 if(pItem->val.uint64 < INT64_MAX) {
4457 *pnValue = pItem->val.int64;
4458 } else {
4459 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4460 }
4461 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004462 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004463 }
4464 break;
4465
4466 default:
4467 return QCBOR_ERR_UNEXPECTED_TYPE;
4468 }
4469 return QCBOR_SUCCESS;
4470}
4471
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004473void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004475 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004476 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004477{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004478 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004479 return;
4480 }
4481
Laurence Lundbladee6430642020-03-14 21:15:44 -07004482 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004483 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4484 if(uError) {
4485 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004486 return;
4487 }
4488
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004489 if(pItem) {
4490 *pItem = Item;
4491 }
4492
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004493 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004494}
4495
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004496
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004497void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4498 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004500 int64_t *pnValue,
4501 QCBORItem *pItem)
4502{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004503 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004504 if(pMe->uLastError != QCBOR_SUCCESS) {
4505 return;
4506 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004507
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004509}
4510
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004511
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004512void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4513 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004514 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004515 int64_t *pnValue,
4516 QCBORItem *pItem)
4517{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004518 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004519 if(pMe->uLastError != QCBOR_SUCCESS) {
4520 return;
4521 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004522
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004523 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004524}
4525
4526
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004527/*
4528 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004529
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004530 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531
Laurence Lundblade93d89472020-10-03 22:30:50 -07004532 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4533 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534
4535 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4536
Laurence Lundblade93d89472020-10-03 22:30:50 -07004537 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4538 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004539 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004540static QCBORError
4541Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004542{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004543 switch(pItem->uDataType) {
4544
4545 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004546 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004547 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004548 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004550 }
4551 break;
4552
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004553 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004554 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004555 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004556 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004557 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004558 }
4559 break;
4560
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004561#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004562 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004564 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004565 pItem->val.expAndMantissa.nExponent,
4566 pnValue,
4567 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004568 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004569 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004570 }
4571 break;
4572
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004573 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004574 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004575 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004576 pItem->val.expAndMantissa.nExponent,
4577 pnValue,
4578 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004579 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004580 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004581 }
4582 break;
4583
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004584 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004585 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004586 int64_t nMantissa;
4587 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004588 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4589 if(uErr) {
4590 return uErr;
4591 }
4592 return ExponentiateNN(nMantissa,
4593 pItem->val.expAndMantissa.nExponent,
4594 pnValue,
4595 Exponentitate10);
4596 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004597 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004598 }
4599 break;
4600
4601 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004603 int64_t nMantissa;
4604 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004605 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4606 if(uErr) {
4607 return uErr;
4608 }
4609 return ExponentiateNN(nMantissa,
4610 pItem->val.expAndMantissa.nExponent,
4611 pnValue,
4612 Exponentitate10);
4613 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004614 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004615 }
4616 break;
4617
4618 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004619 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004620 int64_t nMantissa;
4621 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004622 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4623 if(uErr) {
4624 return uErr;
4625 }
4626 return ExponentiateNN(nMantissa,
4627 pItem->val.expAndMantissa.nExponent,
4628 pnValue,
4629 Exponentitate2);
4630 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004632 }
4633 break;
4634
4635 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004636 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004637 int64_t nMantissa;
4638 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004639 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4640 if(uErr) {
4641 return uErr;
4642 }
4643 return ExponentiateNN(nMantissa,
4644 pItem->val.expAndMantissa.nExponent,
4645 pnValue,
4646 Exponentitate2);
4647 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004648 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004649 }
4650 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004651#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004652
Laurence Lundbladee6430642020-03-14 21:15:44 -07004653
Laurence Lundbladec4537442020-04-14 18:53:22 -07004654 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004655 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004656}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657
4658
Laurence Lundbladec4537442020-04-14 18:53:22 -07004659/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004660 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004661 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004662void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004663{
4664 QCBORItem Item;
4665
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004667
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004668 if(pMe->uLastError == QCBOR_SUCCESS) {
4669 // The above conversion succeeded
4670 return;
4671 }
4672
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004673 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004674 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004675 return;
4676 }
4677
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004678 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004679}
4680
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004681
4682/*
4683Public function, see header qcbor/qcbor_decode.h file
4684*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004685void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4686 int64_t nLabel,
4687 uint32_t uConvertTypes,
4688 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004689{
4690 QCBORItem Item;
4691
Laurence Lundblade93d89472020-10-03 22:30:50 -07004692 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4693 nLabel,
4694 uConvertTypes,
4695 pnValue,
4696 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004697
4698 if(pMe->uLastError == QCBOR_SUCCESS) {
4699 // The above conversion succeeded
4700 return;
4701 }
4702
4703 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4704 // The above conversion failed in a way that code below can't correct
4705 return;
4706 }
4707
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004708 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004709}
4710
4711
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712/*
4713Public function, see header qcbor/qcbor_decode.h file
4714*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004715void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4716 const char *szLabel,
4717 uint32_t uConvertTypes,
4718 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004719{
4720 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004721 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4722 szLabel,
4723 uConvertTypes,
4724 pnValue,
4725 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004726
4727 if(pMe->uLastError == QCBOR_SUCCESS) {
4728 // The above conversion succeeded
4729 return;
4730 }
4731
4732 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4733 // The above conversion failed in a way that code below can't correct
4734 return;
4735 }
4736
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004738}
4739
4740
Laurence Lundblade93d89472020-10-03 22:30:50 -07004741static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004742{
4743 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004744 case QCBOR_TYPE_DOUBLE:
4745 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004746#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004747 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004748 // Can't use llround here because it will not convert values
4749 // greater than INT64_MAX and less than UINT64_MAX that
4750 // need to be converted so it is more complicated.
4751 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4752 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4753 if(isnan(pItem->val.dfnum)) {
4754 return QCBOR_ERR_FLOAT_EXCEPTION;
4755 } else if(pItem->val.dfnum < 0) {
4756 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4757 } else {
4758 double dRounded = round(pItem->val.dfnum);
4759 // See discussion in DecodeDateEpoch() for
4760 // explanation of - 0x7ff
4761 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4762 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4763 }
4764 *puValue = (uint64_t)dRounded;
4765 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004766 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004767 if(isnan(pItem->val.fnum)) {
4768 return QCBOR_ERR_FLOAT_EXCEPTION;
4769 } else if(pItem->val.fnum < 0) {
4770 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4771 } else {
4772 float fRounded = roundf(pItem->val.fnum);
4773 // See discussion in DecodeDateEpoch() for
4774 // explanation of - 0x7ff
4775 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4776 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4777 }
4778 *puValue = (uint64_t)fRounded;
4779 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004780 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004781 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4782 // round() and roundf() shouldn't result in exceptions here, but
4783 // catch them to be robust and thorough. Don't try to
4784 // distinguish between the various exceptions because it seems
4785 // they vary by CPU, compiler and OS.
4786 return QCBOR_ERR_FLOAT_EXCEPTION;
4787 }
4788
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004789 } else {
4790 return QCBOR_ERR_UNEXPECTED_TYPE;
4791 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004792#else
4793 return QCBOR_ERR_HW_FLOAT_DISABLED;
4794#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004795 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004796
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004797 case QCBOR_TYPE_INT64:
4798 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4799 if(pItem->val.int64 >= 0) {
4800 *puValue = (uint64_t)pItem->val.int64;
4801 } else {
4802 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4803 }
4804 } else {
4805 return QCBOR_ERR_UNEXPECTED_TYPE;
4806 }
4807 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004809 case QCBOR_TYPE_UINT64:
4810 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4811 *puValue = pItem->val.uint64;
4812 } else {
4813 return QCBOR_ERR_UNEXPECTED_TYPE;
4814 }
4815 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004816
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004817 default:
4818 return QCBOR_ERR_UNEXPECTED_TYPE;
4819 }
4820
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004821 return QCBOR_SUCCESS;
4822}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004823
4824
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004825void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004826 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004828 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004829{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004830 if(pMe->uLastError != QCBOR_SUCCESS) {
4831 return;
4832 }
4833
Laurence Lundbladec4537442020-04-14 18:53:22 -07004834 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004835
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004836 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4837 if(uError) {
4838 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004839 return;
4840 }
4841
Laurence Lundbladea826c502020-05-10 21:07:00 -07004842 if(pItem) {
4843 *pItem = Item;
4844 }
4845
Laurence Lundblade93d89472020-10-03 22:30:50 -07004846 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004847}
4848
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004849
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004850void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004851 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004852 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853 uint64_t *puValue,
4854 QCBORItem *pItem)
4855{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004856 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004857 if(pMe->uLastError != QCBOR_SUCCESS) {
4858 return;
4859 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860
Laurence Lundblade93d89472020-10-03 22:30:50 -07004861 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862}
4863
4864
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004865void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004867 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868 uint64_t *puValue,
4869 QCBORItem *pItem)
4870{
4871 if(pMe->uLastError != QCBOR_SUCCESS) {
4872 return;
4873 }
4874
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004875 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004876 if(pMe->uLastError != QCBOR_SUCCESS) {
4877 return;
4878 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879
Laurence Lundblade93d89472020-10-03 22:30:50 -07004880 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881}
4882
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004883
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004884
Laurence Lundblade93d89472020-10-03 22:30:50 -07004885static QCBORError
4886UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004887{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004888 switch(pItem->uDataType) {
4889
4890 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004891 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004892 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4893 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895 }
4896 break;
4897
4898 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004900 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4901 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004902 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004903 }
4904 break;
4905
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004906#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004907
4908 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004909 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004910 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004911 pItem->val.expAndMantissa.nExponent,
4912 puValue,
4913 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004915 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004916 }
4917 break;
4918
4919 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004920 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4922 pItem->val.expAndMantissa.nExponent,
4923 puValue,
4924 Exponentitate2);
4925 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004926 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004927 }
4928 break;
4929
4930 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004931 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004932 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004933 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004934 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004935 if(uErr != QCBOR_SUCCESS) {
4936 return uErr;
4937 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004938 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939 pItem->val.expAndMantissa.nExponent,
4940 puValue,
4941 Exponentitate10);
4942 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004943 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004944 }
4945 break;
4946
4947 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004948 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004949 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4950 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004951 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004952 }
4953 break;
4954
4955 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004956 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004957 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004958 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004959 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960 if(uErr != QCBOR_SUCCESS) {
4961 return uErr;
4962 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004963 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004964 pItem->val.expAndMantissa.nExponent,
4965 puValue,
4966 Exponentitate2);
4967 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004968 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004969 }
4970 break;
4971
4972 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004973 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004974 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4975 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004976 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004977 }
4978 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004979#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004980 default:
4981 return QCBOR_ERR_UNEXPECTED_TYPE;
4982 }
4983}
4984
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004985
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004986/*
4987 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004988 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004989void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004990{
4991 QCBORItem Item;
4992
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004993 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004994
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004995 if(pMe->uLastError == QCBOR_SUCCESS) {
4996 // The above conversion succeeded
4997 return;
4998 }
4999
5000 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5001 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005002 return;
5003 }
5004
Laurence Lundblade93d89472020-10-03 22:30:50 -07005005 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005006}
5007
Laurence Lundbladec4537442020-04-14 18:53:22 -07005008
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005009/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005010 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005011*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005012void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005013 int64_t nLabel,
5014 uint32_t uConvertTypes,
5015 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016{
5017 QCBORItem Item;
5018
Laurence Lundblade93d89472020-10-03 22:30:50 -07005019 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5020 nLabel,
5021 uConvertTypes,
5022 puValue,
5023 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005024
5025 if(pMe->uLastError == QCBOR_SUCCESS) {
5026 // The above conversion succeeded
5027 return;
5028 }
5029
5030 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5031 // The above conversion failed in a way that code below can't correct
5032 return;
5033 }
5034
Laurence Lundblade93d89472020-10-03 22:30:50 -07005035 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005036}
5037
5038
5039/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005040 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005041*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005042void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005043 const char *szLabel,
5044 uint32_t uConvertTypes,
5045 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005046{
5047 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005048 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5049 szLabel,
5050 uConvertTypes,
5051 puValue,
5052 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005053
5054 if(pMe->uLastError == QCBOR_SUCCESS) {
5055 // The above conversion succeeded
5056 return;
5057 }
5058
5059 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5060 // The above conversion failed in a way that code below can't correct
5061 return;
5062 }
5063
Laurence Lundblade93d89472020-10-03 22:30:50 -07005064 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005065}
5066
5067
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005068
5069
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005070#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005071static QCBORError ConvertDouble(const QCBORItem *pItem,
5072 uint32_t uConvertTypes,
5073 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005074{
5075 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005076 case QCBOR_TYPE_FLOAT:
5077#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5078 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5079 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005080 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005081 *pdValue = (double)pItem->val.fnum;
5082 } else {
5083 return QCBOR_ERR_UNEXPECTED_TYPE;
5084 }
5085 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005086#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005087 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005088#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005089 break;
5090
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005091 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005092 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5093 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005094 *pdValue = pItem->val.dfnum;
5095 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005096 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005097 }
5098 }
5099 break;
5100
5101 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005102#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005103 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005104 // A simple cast seems to do the job with no worry of exceptions.
5105 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005106 *pdValue = (double)pItem->val.int64;
5107
5108 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005109 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005110 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005111#else
5112 return QCBOR_ERR_HW_FLOAT_DISABLED;
5113#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005114 break;
5115
5116 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005117#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005118 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005119 // A simple cast seems to do the job with no worry of exceptions.
5120 // There will be precision loss for some values.
5121 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005122 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005123 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005124 }
5125 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005126#else
5127 return QCBOR_ERR_HW_FLOAT_DISABLED;
5128#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005129
5130 default:
5131 return QCBOR_ERR_UNEXPECTED_TYPE;
5132 }
5133
5134 return QCBOR_SUCCESS;
5135}
5136
5137
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005138void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005139 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005140 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005141 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005142{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005143 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005144 return;
5145 }
5146
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005147 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005148
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005149 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005150 if(uError) {
5151 pMe->uLastError = (uint8_t)uError;
5152 return;
5153 }
5154
5155 if(pItem) {
5156 *pItem = Item;
5157 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005158
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005159 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005160}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005161
Laurence Lundbladec4537442020-04-14 18:53:22 -07005162
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005163void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5164 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005165 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005166 double *pdValue,
5167 QCBORItem *pItem)
5168{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005169 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005170 if(pMe->uLastError != QCBOR_SUCCESS) {
5171 return;
5172 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005173
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005174 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005175}
5176
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005177
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005178void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5179 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005180 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005181 double *pdValue,
5182 QCBORItem *pItem)
5183{
5184 if(pMe->uLastError != QCBOR_SUCCESS) {
5185 return;
5186 }
5187
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005188 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005189 if(pMe->uLastError != QCBOR_SUCCESS) {
5190 return;
5191 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005192
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005193 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005194}
5195
5196
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005197#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005198static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5199{
5200 double dResult;
5201
5202 dResult = 0.0;
5203 const uint8_t *pByte = BigNum.ptr;
5204 size_t uLen = BigNum.len;
5205 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005206 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005207 while(uLen--) {
5208 dResult = (dResult * 256.0) + (double)*pByte++;
5209 }
5210
5211 return dResult;
5212}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005213#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5214
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005215
Laurence Lundblade93d89472020-10-03 22:30:50 -07005216static QCBORError
5217DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005218{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005219#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005220 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005221 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5222
5223 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005224 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005225
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005226#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005227 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005228 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005229 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005230 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5231 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5232 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005233 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005234 }
5235 break;
5236
5237 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005238 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005239 // Underflow gives 0, overflow gives infinity
5240 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5241 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005242 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005243 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005244 }
5245 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005246#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005247
5248 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005249 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005250 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5251 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005252 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005253 }
5254 break;
5255
5256 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005257 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005258 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005259 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005260 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005261 }
5262 break;
5263
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005264#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005265 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005266 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005267 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5268 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5269 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005270 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005271 }
5272 break;
5273
5274 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005275 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005276 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5277 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5278 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005279 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005280 }
5281 break;
5282
5283 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005284 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005285 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5286 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5287 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005288 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005289 }
5290 break;
5291
5292 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005293 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005294 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005295 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5296 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005297 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005298 }
5299 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005300#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005301
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005302 default:
5303 return QCBOR_ERR_UNEXPECTED_TYPE;
5304 }
5305
5306 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005307
5308#else
5309 (void)pItem;
5310 (void)uConvertTypes;
5311 (void)pdValue;
5312 return QCBOR_ERR_HW_FLOAT_DISABLED;
5313#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5314
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005315}
5316
5317
5318/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005319 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005320*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005321void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5322 uint32_t uConvertTypes,
5323 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005324{
5325
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005326 QCBORItem Item;
5327
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005328 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005329
5330 if(pMe->uLastError == QCBOR_SUCCESS) {
5331 // The above conversion succeeded
5332 return;
5333 }
5334
5335 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5336 // The above conversion failed in a way that code below can't correct
5337 return;
5338 }
5339
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005340 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005341}
5342
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005343
5344/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005345 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005346*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005347void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5348 int64_t nLabel,
5349 uint32_t uConvertTypes,
5350 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005351{
5352 QCBORItem Item;
5353
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005354 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005355
5356 if(pMe->uLastError == QCBOR_SUCCESS) {
5357 // The above conversion succeeded
5358 return;
5359 }
5360
5361 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5362 // The above conversion failed in a way that code below can't correct
5363 return;
5364 }
5365
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005366 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
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_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5374 const char *szLabel,
5375 uint32_t uConvertTypes,
5376 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005377{
5378 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005379 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005380
5381 if(pMe->uLastError == QCBOR_SUCCESS) {
5382 // The above conversion succeeded
5383 return;
5384 }
5385
5386 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5387 // The above conversion failed in a way that code below can't correct
5388 return;
5389 }
5390
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005391 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005392}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005393#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005394
5395
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005396
5397
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005398#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005399static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5400{
5401 while((uInt & 0xff00000000000000UL) == 0) {
5402 uInt = uInt << 8;
5403 };
5404
5405 UsefulOutBuf UOB;
5406
5407 UsefulOutBuf_Init(&UOB, Buffer);
5408
5409 while(uInt) {
5410 const uint64_t xx = uInt & 0xff00000000000000UL;
5411 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5412 uInt = uInt << 8;
5413 (void)xx;
5414 }
5415
5416 return UsefulOutBuf_OutUBuf(&UOB);
5417}
5418
5419
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005420static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5421 TagSpecification TagSpec,
5422 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005423{
5424 QCBORError uErr;
5425 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005426 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005427 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005428 if(uErr != QCBOR_SUCCESS) {
5429 goto Done;
5430 }
5431
5432 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5433 break; // Successful exit. Moving on to finish decoding.
5434 }
5435
5436 // The item is an array, which means an undecoded
5437 // mantissa and exponent, so decode it. It will then
5438 // have a different type and exit the loop if.
5439 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5440 if(uErr != QCBOR_SUCCESS) {
5441 goto Done;
5442 }
5443
5444 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005445 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446 }
5447Done:
5448 return uErr;
5449}
5450
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005451
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005452static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453 TagSpecification TagSpec,
5454 QCBORItem *pItem,
5455 int64_t *pnMantissa,
5456 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005457{
5458 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005459
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005460 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005461 if(uErr != QCBOR_SUCCESS) {
5462 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005463 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005464
Laurence Lundblade9b334962020-08-27 10:55:53 -07005465 switch (pItem->uDataType) {
5466
5467 case QCBOR_TYPE_DECIMAL_FRACTION:
5468 case QCBOR_TYPE_BIGFLOAT:
5469 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5470 *pnExponent = pItem->val.expAndMantissa.nExponent;
5471 break;
5472
5473 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5474 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5475 *pnExponent = pItem->val.expAndMantissa.nExponent;
5476 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5477 break;
5478
5479 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5480 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5481 *pnExponent = pItem->val.expAndMantissa.nExponent;
5482 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5483 break;
5484
5485 default:
5486 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5487 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005488
5489 Done:
5490 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005491}
5492
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005493
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005494static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005495 TagSpecification TagSpec,
5496 QCBORItem *pItem,
5497 UsefulBuf BufferForMantissa,
5498 UsefulBufC *pMantissa,
5499 bool *pbIsNegative,
5500 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005501{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005502 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005503
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005505 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005506 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005507 }
5508
5509 uint64_t uMantissa;
5510
5511 switch (pItem->uDataType) {
5512
5513 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005514 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005515 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5516 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5517 *pbIsNegative = false;
5518 } else {
5519 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5520 *pbIsNegative = true;
5521 }
5522 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5523 *pnExponent = pItem->val.expAndMantissa.nExponent;
5524 break;
5525
5526 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005527 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005528 *pnExponent = pItem->val.expAndMantissa.nExponent;
5529 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5530 *pbIsNegative = false;
5531 break;
5532
5533 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005534 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005535 *pnExponent = pItem->val.expAndMantissa.nExponent;
5536 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5537 *pbIsNegative = true;
5538 break;
5539
5540 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005541 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005542 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005543
5544Done:
5545 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005546}
5547
5548
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005549/*
5550 Public function, see header qcbor/qcbor_decode.h file
5551*/
5552void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5553 uint8_t uTagRequirement,
5554 int64_t *pnMantissa,
5555 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005556{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005557 if(pMe->uLastError != QCBOR_SUCCESS) {
5558 return;
5559 }
5560
5561 QCBORItem Item;
5562 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5563 if(uError) {
5564 pMe->uLastError = (uint8_t)uError;
5565 return;
5566 }
5567
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005568 const TagSpecification TagSpec =
5569 {
5570 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005571 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5572 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5573 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005574 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005575
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005576 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005577}
5578
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005579
5580/*
5581 Public function, see header qcbor/qcbor_decode.h file
5582*/
5583void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005584 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005585 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005586 int64_t *pnMantissa,
5587 int64_t *pnExponent)
5588{
5589 if(pMe->uLastError != QCBOR_SUCCESS) {
5590 return;
5591 }
5592
5593 QCBORItem Item;
5594 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5595
5596 const TagSpecification TagSpec =
5597 {
5598 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005599 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5600 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5601 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005602 };
5603
5604 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5605}
5606
5607
5608/*
5609 Public function, see header qcbor/qcbor_decode.h file
5610*/
5611void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005612 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005613 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005614 int64_t *pnMantissa,
5615 int64_t *pnExponent)
5616{
5617 if(pMe->uLastError != QCBOR_SUCCESS) {
5618 return;
5619 }
5620
5621 QCBORItem Item;
5622 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5623
5624 const TagSpecification TagSpec =
5625 {
5626 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005627 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5628 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5629 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005630 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005631
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005632 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5633}
5634
5635
5636/*
5637 Public function, see header qcbor/qcbor_decode.h file
5638*/
5639void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5640 uint8_t uTagRequirement,
5641 UsefulBuf MantissaBuffer,
5642 UsefulBufC *pMantissa,
5643 bool *pbMantissaIsNegative,
5644 int64_t *pnExponent)
5645{
5646 if(pMe->uLastError != QCBOR_SUCCESS) {
5647 return;
5648 }
5649
5650 QCBORItem Item;
5651 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5652 if(uError) {
5653 pMe->uLastError = (uint8_t)uError;
5654 return;
5655 }
5656
5657 const TagSpecification TagSpec =
5658 {
5659 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005660 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5661 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5662 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005663 };
5664
Laurence Lundblade93d89472020-10-03 22:30:50 -07005665 ProcessMantissaAndExponentBig(pMe,
5666 TagSpec,
5667 &Item,
5668 MantissaBuffer,
5669 pMantissa,
5670 pbMantissaIsNegative,
5671 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005672}
5673
5674
5675/*
5676 Public function, see header qcbor/qcbor_decode.h file
5677*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005678void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005679 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005680 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005681 UsefulBuf BufferForMantissa,
5682 UsefulBufC *pMantissa,
5683 bool *pbIsNegative,
5684 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005685{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005686 if(pMe->uLastError != QCBOR_SUCCESS) {
5687 return;
5688 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005689
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005690 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005691 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005692 if(pMe->uLastError != QCBOR_SUCCESS) {
5693 return;
5694 }
5695
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005696 const TagSpecification TagSpec =
5697 {
5698 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005699 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5700 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5701 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005702 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005703
Laurence Lundblade93d89472020-10-03 22:30:50 -07005704 ProcessMantissaAndExponentBig(pMe,
5705 TagSpec,
5706 &Item,
5707 BufferForMantissa,
5708 pMantissa,
5709 pbIsNegative,
5710 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005711}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005712
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005713
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005714/*
5715 Public function, see header qcbor/qcbor_decode.h file
5716*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005717void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005718 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005719 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005720 UsefulBuf BufferForMantissa,
5721 UsefulBufC *pMantissa,
5722 bool *pbIsNegative,
5723 int64_t *pnExponent)
5724{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005725 if(pMe->uLastError != QCBOR_SUCCESS) {
5726 return;
5727 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005728
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005729 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005730 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5731 if(pMe->uLastError != QCBOR_SUCCESS) {
5732 return;
5733 }
5734
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005735 const TagSpecification TagSpec =
5736 {
5737 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005738 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5739 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5740 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005741 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005742
5743 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5744}
5745
5746
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005747/*
5748 Public function, see header qcbor/qcbor_decode.h file
5749*/
5750void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5751 uint8_t uTagRequirement,
5752 int64_t *pnMantissa,
5753 int64_t *pnExponent)
5754{
5755 if(pMe->uLastError != QCBOR_SUCCESS) {
5756 return;
5757 }
5758
5759 QCBORItem Item;
5760 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5761 if(uError) {
5762 pMe->uLastError = (uint8_t)uError;
5763 return;
5764 }
5765 const TagSpecification TagSpec =
5766 {
5767 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005768 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5769 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5770 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005771 };
5772
5773 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5774}
5775
5776
5777/*
5778 Public function, see header qcbor/qcbor_decode.h file
5779*/
5780void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005781 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005782 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005783 int64_t *pnMantissa,
5784 int64_t *pnExponent)
5785{
5786 if(pMe->uLastError != QCBOR_SUCCESS) {
5787 return;
5788 }
5789
5790 QCBORItem Item;
5791 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5792 if(pMe->uLastError != QCBOR_SUCCESS) {
5793 return;
5794 }
5795
5796 const TagSpecification TagSpec =
5797 {
5798 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005799 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5800 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5801 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005802 };
5803
5804 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5805}
5806
5807
5808/*
5809 Public function, see header qcbor/qcbor_decode.h file
5810*/
5811void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005812 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005813 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005814 int64_t *pnMantissa,
5815 int64_t *pnExponent)
5816{
5817 if(pMe->uLastError != QCBOR_SUCCESS) {
5818 return;
5819 }
5820
5821 QCBORItem Item;
5822 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5823 if(pMe->uLastError != QCBOR_SUCCESS) {
5824 return;
5825 }
5826
5827 const TagSpecification TagSpec =
5828 {
5829 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005830 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5831 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5832 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005833 };
5834
5835 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5836}
5837
5838
5839/*
5840 Public function, see header qcbor/qcbor_decode.h file
5841*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005842void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5843 uint8_t uTagRequirement,
5844 UsefulBuf MantissaBuffer,
5845 UsefulBufC *pMantissa,
5846 bool *pbMantissaIsNegative,
5847 int64_t *pnExponent)
5848{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005849 if(pMe->uLastError != QCBOR_SUCCESS) {
5850 return;
5851 }
5852
5853 QCBORItem Item;
5854 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5855 if(uError) {
5856 pMe->uLastError = (uint8_t)uError;
5857 return;
5858 }
5859
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005860 const TagSpecification TagSpec =
5861 {
5862 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005863 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5864 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5865 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005866 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005867
5868 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005869}
5870
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005871
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005872/*
5873 Public function, see header qcbor/qcbor_decode.h file
5874*/
5875void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005876 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005877 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005878 UsefulBuf BufferForMantissa,
5879 UsefulBufC *pMantissa,
5880 bool *pbIsNegative,
5881 int64_t *pnExponent)
5882{
5883 if(pMe->uLastError != QCBOR_SUCCESS) {
5884 return;
5885 }
5886
5887 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005888 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5889 if(pMe->uLastError != QCBOR_SUCCESS) {
5890 return;
5891 }
5892
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005893 const TagSpecification TagSpec =
5894 {
5895 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005896 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5897 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5898 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005899 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005900
Laurence Lundblade93d89472020-10-03 22:30:50 -07005901 ProcessMantissaAndExponentBig(pMe,
5902 TagSpec,
5903 &Item,
5904 BufferForMantissa,
5905 pMantissa,
5906 pbIsNegative,
5907 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005908}
5909
5910
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005911/*
5912 Public function, see header qcbor/qcbor_decode.h file
5913*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005914void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005915 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005916 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005917 UsefulBuf BufferForMantissa,
5918 UsefulBufC *pMantissa,
5919 bool *pbIsNegative,
5920 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005921{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005922 if(pMe->uLastError != QCBOR_SUCCESS) {
5923 return;
5924 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005926 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005927 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5928 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005929 return;
5930 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005931
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005932 const TagSpecification TagSpec =
5933 {
5934 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005935 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5936 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5937 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005938 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005939
Laurence Lundblade93d89472020-10-03 22:30:50 -07005940 ProcessMantissaAndExponentBig(pMe,
5941 TagSpec,
5942 &Item,
5943 BufferForMantissa,
5944 pMantissa,
5945 pbIsNegative,
5946 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005947}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005948
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005949#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */