blob: 3f15d4ab1d75c1c1a4a44eafd10ec2ab88ce7fe1 [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.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080036#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070037
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080039
40#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
44
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080045#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080048
Laurence Lundbladea9489f82020-09-12 13:50:56 -070049#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070051
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080052
53
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070054static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070055QCBORItem_IsMapOrArray(const QCBORItem *pMe)
56{
57 const uint8_t uDataType = pMe->uDataType;
58 return uDataType == QCBOR_TYPE_MAP ||
59 uDataType == QCBOR_TYPE_ARRAY ||
60 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
61}
62
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070063static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070064QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
65{
66 if(!QCBORItem_IsMapOrArray(pMe)){
67 return false;
68 }
69
70 if(pMe->val.uCount != 0) {
71 return false;
72 }
73 return true;
74}
75
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070076static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070077QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
78{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080079#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070080 if(!QCBORItem_IsMapOrArray(pMe)){
81 return false;
82 }
83
84 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
85 return false;
86 }
87 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080088#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
89 (void)pMe;
90 return false;
91#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070092}
93
94
Laurence Lundbladeee851742020-01-08 08:37:05 -080095/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070096 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080097 ===========================================================================*/
98
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800100 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
101 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700102 */
103
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700104
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700105static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700106DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700107{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700108 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800109 /* Limit in DecodeNesting_Descend against more than
110 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700111 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700112 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113}
114
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700115
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700116static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700117DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700118{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700119 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800120 /* Limit in DecodeNesting_Descend against more than
121 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700122 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700123 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124}
125
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700126
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700127static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700128DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700129{
130 return pNesting->pCurrentBounded->u.ma.uStartOffset;
131}
132
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700133
Laurence Lundblade085d7952020-07-24 10:26:30 -0700134static inline bool
135DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
136{
137 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
138 return true;
139 } else {
140 return false;
141 }
142}
143
144
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700145static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700146DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700147{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700148 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700149 return true;
150 } else {
151 return false;
152 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153}
154
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700155
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700156static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158{
159 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800160 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700161 return false;
162 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800163
164#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700165 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800166 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return false;
168 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800169
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800170#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
171
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800172 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return true;
174}
175
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700176static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700178{
179 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800180 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700181 return true;
182 }
183 return false;
184}
185
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700186
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700187static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700188{
189 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
190 return true;
191 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700192 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193 return true;
194 }
195 return false;
196}
197
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700198
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700199static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800201 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700202 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800203 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
204 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
205 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700206 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700207 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700208
209 if(bIsEmpty) {
210 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
211 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700212}
213
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700215static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700216{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700217 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218}
219
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700220
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700221static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700222DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223{
224 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800225 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700226 return false;
227 }
228 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800229 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700230 return false;
231 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700232 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800233 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700234 return false;
235 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800236 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800237 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
238 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800239 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800242 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700243 return true;
244}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700245
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700246
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700247static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700248DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700249{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800250 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700251 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
252 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700253 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700254 return false;
255 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700256}
257
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700258
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700259static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700260DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700261{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
263 return true;
264 } else {
265 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700266 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700267}
268
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700269
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700270static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700271DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700272{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700273 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700274 return false;
275 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700276
277 if(pNesting->pCurrentBounded->uLevelType != uType) {
278 return false;
279 }
280
281 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700282}
283
Laurence Lundblade02625d42020-06-25 14:41:41 -0700284
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700285static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700286DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700287{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800288 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700289 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700290}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700291
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700292
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700293static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700294DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
295{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800296 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700297 pNesting->pCurrent->u.ma.uCountCursor++;
298}
299
300
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700301static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700302DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
303{
304 pNesting->pCurrent--;
305}
306
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307
308static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700309DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700310{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800311 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700312 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700313 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700314 }
315
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800316 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700317 pNesting->pCurrent++;
318
319 pNesting->pCurrent->uLevelType = uType;
320
321 return QCBOR_SUCCESS;
322}
323
324
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700325static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800326DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
327 bool bIsEmpty,
328 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700329{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700330 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800331 * Should only be called on map/array.
332 *
333 * Have descended into this before this is called. The job here is
334 * just to mark it in bounded mode.
335 *
336 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
337 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
338 *
339 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700340 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800341 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700342 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700343 }
344
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700345 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700346
347 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700348
349 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700350}
351
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700352
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700353static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700354DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700355 uint8_t uQCBORType,
356 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700358 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700359
360 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800361 /* Nothing to do for empty definite-length arrays. They are just are
362 * effectively the same as an item that is not a map or array.
363 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700364 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800365 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700366 }
367
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800368 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700369 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
370 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700371 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 goto Done;
373 }
374
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700375 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700376 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700377 goto Done;
378 }
379
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800380 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700381 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
382 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700383
384 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700385
386Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 return uError;;
388}
389
390
391static inline void
392DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
393{
394 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
395}
396
397
398static inline void
399DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
400{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700401 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402 pNesting->pCurrentBounded--;
403 if(DecodeNesting_IsCurrentBounded(pNesting)) {
404 break;
405 }
406 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700407}
408
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800409
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700410static inline void
411DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
412{
413 pNesting->pCurrent = pNesting->pCurrentBounded;
414}
415
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700416
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700417static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700418DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700419 uint32_t uEndOffset,
420 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700422 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700423
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700424 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700425 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700426 goto Done;
427 }
428
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800429 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700430 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
431 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800433 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700434 pNesting->pCurrentBounded = pNesting->pCurrent;
435
436Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700437 return uError;;
438}
439
Laurence Lundbladed0304932020-06-27 10:59:38 -0700440
441static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443{
444 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700445}
446
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700447
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700448static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800449DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
450{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700451 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
452 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
453 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800454}
455
456
457static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700458DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700459{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
462 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463}
464
465
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700466static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800467DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
468 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700469{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700470 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700471}
472
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800475DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
476 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700477{
478 *pNesting = *pSave;
479}
480
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700481
Laurence Lundblade02625d42020-06-25 14:41:41 -0700482static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700483DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700484{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700485 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700486}
487
488
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800489
490
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800491#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800493 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
494
495 The following four functions are pretty wrappers for invocation of
496 the string allocator supplied by the caller.
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499
Laurence Lundbladeee851742020-01-08 08:37:05 -0800500static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800501StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800503 /* These pragmas allow the "-Wcast-qual" warnings flag to be set for
504 * gcc and clang. This is the one place where the const needs to be
505 * cast away so const can be use in the rest of the code.
506 */
507#pragma GCC diagnostic push
508#pragma GCC diagnostic ignored "-Wcast-qual"
509 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
510#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800511}
512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513// StringAllocator_Reallocate called with pMem NULL is
514// equal to StringAllocator_Allocate()
515static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800516StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800517 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800519{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800520 /* See comment in StringAllocator_Free() */
521#pragma GCC diagnostic push
522#pragma GCC diagnostic ignored "-Wcast-qual"
523 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
524#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525}
526
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800528StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800529{
530 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
531}
532
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800534StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800535{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800536 /* See comment in StringAllocator_Free() */
537#pragma GCC diagnostic push
538#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800539 if(pMe->pfAllocator) {
540 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
541 }
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800542#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800544#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800545
546
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800547
548
Laurence Lundbladeee851742020-01-08 08:37:05 -0800549/*===========================================================================
550 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700551
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800552 See qcbor/qcbor_decode.h for definition of the object
553 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800556 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800558void QCBORDecode_Init(QCBORDecodeContext *pMe,
559 UsefulBufC EncodedCBOR,
560 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800562 memset(pMe, 0, sizeof(QCBORDecodeContext));
563 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
564 /* Don't bother with error check on decode mode. If a bad value is
565 * passed it will just act as if the default normal mode of 0 was set.
566 */
567 pMe->uDecodeMode = (uint8_t)nDecodeMode;
568 DecodeNesting_Init(&(pMe->nesting));
569
570 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
571 * GetNext_TaggedItem() and MapTagNumber(). */
572 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700573}
574
575
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800576#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
577
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800579 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800581void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
582 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800583 void *pAllocateContext,
584 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700585{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800586 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
587 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
588 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800590#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800593
594
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800595/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800596 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800597 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800598void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800599 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700600{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800601 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700602 (void)pMe;
603 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700604}
605
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700606
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800607
608
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700609/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800610 * Decoding items is done in six layers, one calling the next one
611 * down. If a layer has no work to do for a particular item, it
612 * returns quickly.
613 *
614 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
615 * data items, turning them into the local C representation. For the
616 * most simple it is just associating a QCBOR_TYPE with the data. For
617 * the complex ones that an aggregate of data items, there is some
618 * further decoding and some limited recursion.
619 *
620 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
621 * ends of maps and arrays. It tracks descending into and ascending
622 * out of maps/arrays. It processes breaks that terminate
623 * indefinite-length maps and arrays.
624 *
625 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
626 * items, the label and the data, that make up a map entry. It only
627 * does work on maps. It combines the label and data items into one
628 * labeled item.
629 *
630 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
631 * numbers. It turns the tag numbers into bit flags associated with
632 * the data item. No actual decoding of the contents of the tag is
633 * performed here.
634 *
635 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
636 * that make up an indefinite-length string into one string item. It
637 * uses the string allocator to create contiguous space for the
638 * item. It processes all breaks that are part of indefinite-length
639 * strings.
640 *
641 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
642 * CBOR. Each atomic data item has a "major type", an integer
643 * "argument" and optionally some content. For text and byte strings,
644 * the content is the bytes that make up the string. These are the
645 * smallest data items that are considered to be well-formed. The
646 * content may also be other data items in the case of aggregate
647 * types. They are not handled in this layer.
648 *
649 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
650 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800652
653
654/*
655 * Note about use of int and unsigned variables.
656 *
657 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
658 * used carefully here, and in particular why it isn't used in the
659 * public interface. Also see
660 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
661 *
662 * Int is used for values that need less than 16-bits and would be
663 * subject to integer promotion and result in complaining from static
664 * analyzers.
665 */
666
667
668/**
669 * @brief Decode the CBOR head, the type and argument.
670 *
671 * @param[in] pUInBuf The input buffer to read from.
672 * @param[out] pnMajorType The decoded major type.
673 * @param[out] puArgument The decoded argument.
674 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
675 *
676 * @retval QCBOR_ERR_UNSUPPORTED
677 * @retval QCBOR_ERR_HIT_END
678 *
679 * This decodes the CBOR "head" that every CBOR data item has. See
680 * longer explaination of the head in documentation for
681 * QCBOREncode_EncodeHead().
682 *
683 * This does the network->host byte order conversion. The conversion
684 * here also results in the conversion for floats in addition to that
685 * for lengths, tags and integer values.
686 *
687 * The int type is preferred to uint8_t for some variables as this
688 * avoids integer promotions, can reduce code size and makes static
689 * analyzers happier.
690 */
691static inline QCBORError
692DecodeHead(UsefulInputBuf *pUInBuf,
693 int *pnMajorType,
694 uint64_t *puArgument,
695 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800697 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800698
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800699 /* Get the initial byte that every CBOR data item has and break it
700 * down. */
701 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800702 const int nTmpMajorType = nInitialByte >> 5;
703 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800704
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800705 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800706 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800708 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800709 /* Need to get 1,2,4 or 8 additional argument bytes. Map
710 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
711 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800712 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800714 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800715 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800716 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800717 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800718 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
719 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800720 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800721 /* The reserved and thus-far unused additional info values */
722 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800723 goto Done;
724 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800725 /* Less than 24, additional info is argument or 31, an
726 * indefinite-length. No more bytes to get.
727 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800728 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800730
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700731 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800732 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733 goto Done;
734 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800735
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800736 /* All successful if arrived here. */
737 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800739 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800740 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800743 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744}
745
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800747/**
748 * @brief Decode integer types, major types 0 and 1.
749 *
750 * @param[in] nMajorType The CBOR major type (0 or 1).
751 * @param[in] uArgument The argument from the head.
752 * @param[out] pDecodedItem The filled in decoded item.
753 *
754 * @retval QCBOR_ERR_INT_OVERFLOW
755 *
756 * Must only be called when major type is 0 or 1.
757 *
758 * CBOR doesn't explicitly specify two's compliment for integers but
759 * all CPUs use it these days and the test vectors in the RFC are
760 * so. All integers in the CBOR structure are positive and the major
761 * type indicates positive or negative. CBOR can express positive
762 * integers up to 2^x - 1 where x is the number of bits and negative
763 * integers down to 2^x. Note that negative numbers can be one more
764 * away from zero than positive. Stdint, as far as I can tell, uses
765 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700766 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700767static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800768DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800770 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800771
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800773 if (uArgument <= INT64_MAX) {
774 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700775 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800776
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700777 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800778 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700779 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800783 if(uArgument <= INT64_MAX) {
784 /* CBOR's representation of negative numbers lines up with
785 * the two-compliment representation. A negative integer has
786 * one more in range than a positive integer. INT64_MIN is
787 * equal to (-INT64_MAX) - 1.
788 */
789 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800793 /* C can't represent a negative integer in this range so it
794 * is an error.
795 */
796 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797 }
798 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800800 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700801}
802
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800803
804/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
806#error QCBOR_TYPE_FALSE macro value wrong
807#endif
808
809#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
810#error QCBOR_TYPE_TRUE macro value wrong
811#endif
812
813#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
814#error QCBOR_TYPE_NULL macro value wrong
815#endif
816
817#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
818#error QCBOR_TYPE_UNDEF macro value wrong
819#endif
820
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700821#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
822#error QCBOR_TYPE_BREAK macro value wrong
823#endif
824
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
826#error QCBOR_TYPE_DOUBLE macro value wrong
827#endif
828
829#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
830#error QCBOR_TYPE_FLOAT macro value wrong
831#endif
832
Laurence Lundblade9b334962020-08-27 10:55:53 -0700833
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800834/**
835 * @brief Decode major type 7 -- true, false, floating-point, break...
836 *
837 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
838 * @param[in] uArgument The argument from the head.
839 * @param[out] pDecodedItem The filled in decoded item.
840 *
841 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
842 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700843 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800844
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800845static inline QCBORError
846DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
847{
848 QCBORError uReturn = QCBOR_SUCCESS;
849
850 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
851 * checks above make sure uAdditionalInfo values line up with
852 * uDataType values. DecodeHead() never returns an AdditionalInfo
853 * > 0x1f so cast is safe.
854 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800858 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
859 * are caught before this is called.
860 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800862 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700863#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864 /* Half-precision is returned as a double. The cast to
865 * uint16_t is safe because the encoded value was 16 bits. It
866 * was widened to 64 bits to be passed in here.
867 */
868 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700869 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800870#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800871 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800872#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700873 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800874 case SINGLE_PREC_FLOAT: /* 26 */
875 /* Single precision is normally returned as a double since
876 * double is widely supported, there is no loss of precision,
877 * it makes it easy for the caller in most cases and it can
878 * be converted back to single with no loss of precision
879 *
880 * The cast to uint32_t is safe because the encoded value was
881 * 32 bits. It was widened to 64 bits to be passed in here.
882 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800884 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800886 /* In the normal case, use HW to convert float to
887 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700888 pDecodedItem->val.dfnum = (double)f;
889 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800890#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800891 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700892 pDecodedItem->val.fnum = f;
893 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895 /* IEEE754_FloatToDouble() could be used here to return as
896 * a double, but it adds object code and most likely
897 * anyone disabling FLOAT HW use doesn't care about floats
898 * and wants to save object code.
899 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800900#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700901 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700902 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700903
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800904 case DOUBLE_PREC_FLOAT: /* 27 */
905 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700906 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700907 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800909 case CBOR_SIMPLEV_FALSE: /* 20 */
910 case CBOR_SIMPLEV_TRUE: /* 21 */
911 case CBOR_SIMPLEV_NULL: /* 22 */
912 case CBOR_SIMPLEV_UNDEF: /* 23 */
913 case CBOR_SIMPLE_BREAK: /* 31 */
914 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800916 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
917 if(uArgument <= CBOR_SIMPLE_BREAK) {
918 /* This takes out f8 00 ... f8 1f which should be encoded
919 * as e0 … f7
920 */
921 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922 goto Done;
923 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800924 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800928 /* DecodeHead() will make uArgument equal to
929 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
930 * safe because the 2, 4 and 8 byte lengths of uNumber are in
931 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800932 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800933 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 break;
935 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700937Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800938 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700939}
940
941
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800942/**
943 * @brief Decode text and byte strings
944 *
945 * @param[in] pAllocator The string allocator or NULL.
946 * @param[in] uStrLen The length of the string.
947 * @param[in] pUInBuf The surce from which to read the string's bytes.
948 * @param[out] pDecodedItem The filled in decoded item.
949 *
950 * @retval QCBOR_ERR_HIT_END
951 * @retval QCBOR_ERR_STRING_ALLOCATE
952 * @retval QCBOR_ERR_STRING_TOO_LONG
953 *
954 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
955 * pDecodedItem. If @c pAllocator is not NULL then memory for the
956 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800958static inline QCBORError
959DecodeBytes(const QCBORInternalAllocator *pAllocator,
960 uint64_t uStrLen,
961 UsefulInputBuf *pUInBuf,
962 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800964 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800965
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800966 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
967 * CPUs. This check makes the casts to size_t below safe.
968 *
969 * The max is 4 bytes less than the largest sizeof() so this can be
970 * tested by putting a SIZE_MAX length in the CBOR test input (no
971 * one will care the limit on strings is 4 bytes shorter).
972 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800974 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800975 goto Done;
976 }
977
978 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530979 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800980 /* Failed to get the bytes for this string item */
981 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530982 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530984
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800985#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800986 /* Note that this is not where allocation to coalesce
987 * indefinite-length strings is done. This is for when the caller
988 * has requested all strings be allocated. Disabling indefinite
989 * length strings also disables this allocate-all option.
990 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800991 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800992 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800993 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530994 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800995 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530996 goto Done;
997 }
998 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800999 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001000 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301001 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001002#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1003 (void)pAllocator;
1004#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1005
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001006 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001007 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301009Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001010 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011}
1012
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001013
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001014/**
1015 * @brief Map the CBOR major types for strings to the QCBOR types.
1016 *
1017 * @param[in] nCBORMajorType The CBOR major type to convert.
1018 * @retturns QCBOR type number.
1019 *
1020 * This only works for the two string types.
1021 */
1022static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023{
1024 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1025 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1026 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001028 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1029 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1030 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001031
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001032 return (uint8_t)(nCBORMajorType + 4);
1033}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001034
1035
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001036/**
1037 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1038 *
1039 * @param[in] nCBORMajorType The CBOR major type to convert.
1040 * @retturns QCBOR type number.
1041 *
1042 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001043 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001044static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001046 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1047 #error QCBOR_TYPE_ARRAY value not lined up with major type
1048 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001049
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001050 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1051 #error QCBOR_TYPE_MAP value not lined up with major type
1052 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001054 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055}
1056
1057
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001058/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001059 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001060 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001061 * @param[in] pUInBuf Input buffer to read data item from.
1062 * @param[out] pDecodedItem The filled-in decoded item.
1063 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001064 *
1065 * @retval QCBOR_ERR_UNSUPPORTED
1066 * @retval QCBOR_ERR_HIT_END
1067 * @retval QCBOR_ERR_INT_OVERFLOW
1068 * @retval QCBOR_ERR_STRING_ALLOCATE
1069 * @retval QCBOR_ERR_STRING_TOO_LONG
1070 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1071 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001072 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1073 *
1074 * This decodes the most primitive / atomic data item. It does
1075 * no combing of data items.
1076 */
1077static QCBORError
1078DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1079 QCBORItem *pDecodedItem,
1080 const QCBORInternalAllocator *pAllocator)
1081{
1082 QCBORError uReturn;
1083
1084 /* Get the major type and the argument. The argument could be
1085 * length of more bytes or the value depending on the major
1086 * type. nAdditionalInfo is an encoding of the length of the
1087 * uNumber and is needed to decode floats and doubles.
1088 */
1089 int nMajorType = 0;
1090 uint64_t uArgument = 0;
1091 int nAdditionalInfo = 0;
1092
1093 memset(pDecodedItem, 0, sizeof(QCBORItem));
1094
1095 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1096 if(uReturn) {
1097 goto Done;
1098 }
1099
1100 /* At this point the major type and the argument are valid. We've
1101 * got the type and the argument that starts every CBOR data item.
1102 */
1103 switch (nMajorType) {
1104 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1105 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1106 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1107 uReturn = QCBOR_ERR_BAD_INT;
1108 } else {
1109 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1110 }
1111 break;
1112
1113 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1114 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1115 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1116 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1117 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1118 } else {
1119 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1120 }
1121 break;
1122
1123 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1124 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1125 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1126 /* Indefinite-length string. */
1127#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1128 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1129#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1130 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1131 break;
1132#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1133 } else {
1134 /* Definite-length string. */
1135 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1136 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1137 goto Done;
1138 }
1139 /* cast OK because of check above */
1140 pDecodedItem->val.uCount = (uint16_t)uArgument;
1141 }
1142 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1143 break;
1144
1145 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1146 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1147 uReturn = QCBOR_ERR_BAD_INT;
1148 } else {
1149 pDecodedItem->val.uTagV = uArgument;
1150 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1151 }
1152 break;
1153
1154 case CBOR_MAJOR_TYPE_SIMPLE:
1155 /* Major type 7: float, double, true, false, null... */
1156 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1157 break;
1158
1159 default:
1160 /* Never happens because DecodeHead() should never return > 7 */
1161 uReturn = QCBOR_ERR_UNSUPPORTED;
1162 break;
1163 }
1164
1165Done:
1166 return uReturn;
1167}
1168
1169
1170/**
1171 * @brief Process indefinite-length strings (decode layer 5).
1172 *
1173 * @param[in] pMe Decoder context
1174 * @param[out] pDecodedItem The decoded item that work is done on.
1175 *
1176 * @retval QCBOR_ERR_UNSUPPORTED
1177 * @retval QCBOR_ERR_HIT_END
1178 * @retval QCBOR_ERR_INT_OVERFLOW
1179 * @retval QCBOR_ERR_STRING_ALLOCATE
1180 * @retval QCBOR_ERR_STRING_TOO_LONG
1181 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1182 * @retval QCBOR_ERR_BAD_TYPE_7
1183 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1185 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001186 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001188 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001190 * If it is, this loops getting the subsequent chunk data items that
1191 * make up the string. The string allocator is used to make a
1192 * contiguous buffer for the chunks. When this completes @c
1193 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001194 *
1195 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001196 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001197static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001198QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001199{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001200 /* Aproximate stack usage
1201 * 64-bit 32-bit
1202 * local vars 32 16
1203 * 2 UsefulBufs 32 16
1204 * QCBORItem 56 52
1205 * TOTAL 120 74
1206 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001207
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001208 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001209 * coalescing the chunks of an indefinite-length string, 2)
1210 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001211 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001212 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001213 * strings cannot be processed at all without a string allocator.
1214 *
1215 * The second used is in DecodeBytes() which is called by
1216 * GetNext_Item() below. This second use unneccessary for most use
1217 * and only happens when requested in the call to
1218 * QCBORDecode_SetMemPool(). If the second use not requested then
1219 * NULL is passed for the string allocator to GetNext_Item().
1220 *
1221 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1222 * allocator altogether and thus both of these uses. It reduced the
1223 * decoder object code by about 400 bytes.
1224 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001225 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001226
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001227#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001228 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001229
1230 if(pMe->StringAllocator.pfAllocator) {
1231 pAllocator = &(pMe->StringAllocator);
1232 if(pMe->bStringAllocateAll) {
1233 pAllocatorForGetNext = pAllocator;
1234 }
1235 }
1236#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1237
1238 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001239 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001240 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001241 goto Done;
1242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001244 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001245 const uint8_t uStringType = pDecodedItem->uDataType;
1246 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001247 goto Done;
1248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001249
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001250 /* Is this a string with an indefinite length? */
1251 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1252 goto Done;
1253 }
1254
1255#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001256 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001257 if(pAllocator == NULL) {
1258 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1259 goto Done;
1260 }
1261
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001262 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001263 UsefulBufC FullString = NULLUsefulBufC;
1264
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001265 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001266 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001267 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001268 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001269 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001270 * be allocated. They are always copied in the the contiguous
1271 * buffer allocated here.
1272 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001273 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001274 if(uReturn) {
1275 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001277
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001278 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001279 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001280 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001281 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301282 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001283 break;
1284 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001285
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001286 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001287 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001288 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001289 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001290 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001291 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1293 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001294 break;
1295 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001296
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 /* The first time throurgh FullString.ptr is NULL and this is
1298 * equivalent to StringAllocator_Allocate(). Subsequently it is
1299 * not NULL and a reallocation happens.
1300 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001301 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001302 FullString.ptr,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001303 FullString.len + StringChunkItem.val.string.len);
1304
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001305 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001306 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001307 break;
1308 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001309
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001310 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001311 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001312 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001313
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001314 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1315 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001316 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001317 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001318#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1319 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1320#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001321
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001322Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001323 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001324}
1325
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001326
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001327/**
1328 * @brief This converts a tag number to a shorter mapped value for storage.
1329 *
1330 * @param[in] pMe The decode context.
1331 * @param[in] uUnMappedTag The tag number to map
1332 * @param[out] puMappedTagNumer The stored tag number.
1333 *
1334 * @return error code.
1335 *
1336 * The main point of mapping tag numbers is make QCBORItem
1337 * smaller. With this mapping storage of 4 tags takes up 8
1338 * bytes. Without, it would take up 32 bytes.
1339 *
1340 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1341 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1342 *
1343 * See also UnMapTagNumber() and @ref QCBORItem.
1344 */
1345static inline QCBORError
1346MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1347{
1348 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1349 unsigned uTagMapIndex;
1350 /* Is there room in the tag map, or is it in it already? */
1351 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1352 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1353 break;
1354 }
1355 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1356 break;
1357 }
1358 }
1359 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1360 return QCBOR_ERR_TOO_MANY_TAGS;
1361 }
1362
1363 /* Covers the cases where tag is new and were it is already in the map */
1364 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1365 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1366
1367 } else {
1368 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1369 }
1370
1371 return QCBOR_SUCCESS;
1372}
1373
1374
1375/**
1376 * @brief This converts a mapped tag number to the actual tag number.
1377 *
1378 * @param[in] pMe The decode context.
1379 * @param[in] uMappedTagNumber The stored tag number.
1380 *
1381 * @return The actual tag number is returned or
1382 * @ref CBOR_TAG_INVALID64 on error.
1383 *
1384 * This is the reverse of MapTagNumber()
1385 */
1386static uint64_t
1387UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1388{
1389 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1390 return uMappedTagNumber;
1391 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001392 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001393 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001394 /* This won't be negative because of code below in
1395 * MapTagNumber()
1396 */
1397 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1398 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001399 }
1400}
1401
Laurence Lundblade9b334962020-08-27 10:55:53 -07001402
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001403/**
1404 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1405 *
1406 * @param[in] pMe Decoder context
1407 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001408
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001409 * @retval QCBOR_ERR_UNSUPPORTED
1410 * @retval QCBOR_ERR_HIT_END
1411 * @retval QCBOR_ERR_INT_OVERFLOW
1412 * @retval QCBOR_ERR_STRING_ALLOCATE
1413 * @retval QCBOR_ERR_STRING_TOO_LONG
1414 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1415 * @retval QCBOR_ERR_BAD_TYPE_7
1416 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1417 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1418 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1419 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1420 * @retval QCBOR_ERR_TOO_MANY_TAGS
1421 *
1422 * This loops getting atomic data items until one is not a tag
1423 * number. Usually this is largely pass-through because most
1424 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001425 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001426static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001427QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001428{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001429 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1430
1431 /* Initialize to CBOR_TAG_INVALID16 */
1432 #if CBOR_TAG_INVALID16 != 0xffff
1433 /* Be sure the memset does the right thing. */
1434 #err CBOR_TAG_INVALID16 tag not defined as expected
1435 #endif
1436 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001437
Laurence Lundblade9b334962020-08-27 10:55:53 -07001438 QCBORError uReturn = QCBOR_SUCCESS;
1439
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001440 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001441 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001442 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001443 if(uErr != QCBOR_SUCCESS) {
1444 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001445 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001446 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001447
Laurence Lundblade9b334962020-08-27 10:55:53 -07001448 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001449 /* Successful exit from loop; maybe got some tags, maybe not */
1450 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001451 break;
1452 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001453
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001454 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1455 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001456 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001457 /* Continue on to get all tags wrapping this item even though
1458 * it is erroring out in the end. This allows decoding to
1459 * continue. This is a resource limit error, not a problem
1460 * with being well-formed CBOR.
1461 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001462 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001463 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001464 /* Slide tags over one in the array to make room at index 0.
1465 * Must use memmove because the move source and destination
1466 * overlap.
1467 */
1468 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001469
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001470 /* Map the tag */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001471 uint16_t uMappedTagNumer = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001472 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1473 /* Continue even on error so as to consume all tags wrapping
1474 * this data item so decoding can go on. If MapTagNumber()
1475 * errors once it will continue to error.
1476 */
1477 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001478 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001479
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001480Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001481 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001482}
1483
1484
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001485/**
1486 * @brief Combine a map entry label and value into one item (decode layer 3).
1487 *
1488 * @param[in] pMe Decoder context
1489 * @param[out] pDecodedItem The decoded item that work is done on.
1490 *
1491 * @retval QCBOR_ERR_UNSUPPORTED
1492 * @retval QCBOR_ERR_HIT_END
1493 * @retval QCBOR_ERR_INT_OVERFLOW
1494 * @retval QCBOR_ERR_STRING_ALLOCATE
1495 * @retval QCBOR_ERR_STRING_TOO_LONG
1496 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1497 * @retval QCBOR_ERR_BAD_TYPE_7
1498 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1499 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1500 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1501 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1502 * @retval QCBOR_ERR_TOO_MANY_TAGS
1503 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1504 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1505 *
1506 * If a the current nesting level is a map, then this
1507 * combines pairs of items into one data item with a label
1508 * and value.
1509 *
1510 * This is pass-through if the current nesting leve is
1511 * not a map.
1512 *
1513 * This also implements maps-as-array mode where a map
1514 * is treated like an array to allow caller to do their
1515 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001516 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001517static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001518QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001519{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001520 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1521 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001522 goto Done;
1523 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001524
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001525 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1526 /* Break can't be a map entry */
1527 goto Done;
1528 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001529
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001530 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1531 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001532
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001533 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1534 /* Save label in pDecodedItem and get the next which will
1535 * be the real data item.
1536 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001537 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001538 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1539 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001540 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001541 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301543 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001544
1545 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001546 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001547 pDecodedItem->label.string = LabelItem.val.string;
1548 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001549 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1550 /* It's not a string and we only want strings */
1551 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001552 goto Done;
1553 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1554 pDecodedItem->label.int64 = LabelItem.val.int64;
1555 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1556 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1557 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1558 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1559 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1560 pDecodedItem->label.string = LabelItem.val.string;
1561 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1562 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1563 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 /* label is not an int or a string. It is an arrray
1565 * or a float or such and this implementation doesn't handle that.
1566 * Also, tags on labels are ignored.
1567 */
1568 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001569 goto Done;
1570 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001571 }
1572 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001573 /* Decoding of maps as arrays to let the caller decide what to do
1574 * about labels, particularly lables that are not integers or
1575 * strings.
1576 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001577 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001578 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001579 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001580 goto Done;
1581 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001582 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001583 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1584 * Cast is needed because of integer promotion.
1585 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001586 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001587 }
1588 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001589
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001590Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001591 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001592}
1593
1594
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001595#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001596/**
1597 * @brief Peek and see if next data item is a break;
1598 *
1599 * @param[in] pUIB UsefulInputBuf to read from.
1600 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1601 *
1602 * @return Any decoding error.
1603 *
1604 * See if next item is a CBOR break. If it is, it is consumed,
1605 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001606*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001608NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1609{
1610 *pbNextIsBreak = false;
1611 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001612 QCBORItem Peek;
1613 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001614 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001615 if(uReturn != QCBOR_SUCCESS) {
1616 return uReturn;
1617 }
1618 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001619 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001620 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001621 } else {
1622 *pbNextIsBreak = true;
1623 }
1624 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001625
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001626 return QCBOR_SUCCESS;
1627}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001628#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001629
1630
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001631/**
1632 * @brief Ascend up nesting levels if all items in them have been consumed.
1633 *
1634 * @param[in] pMe The decode context.
1635 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1636 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001637 * An item was just consumed, now figure out if it was the
1638 * end of an array/map map that can be closed out. That
1639 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001640*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001641static QCBORError
1642QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001643{
1644 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001645
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001646 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001647 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1648
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001649 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1650 /* Nesting level is bstr-wrapped CBOR */
1651
1652 /* Ascent for bstr-wrapped CBOR is always by explicit call
1653 * so no further ascending can happen.
1654 */
1655 break;
1656
1657 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1658 /* Level is a definite-length array/map */
1659
1660 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001661 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1662 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001663 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001664 break;
1665 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001666 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001667 * is time to ascend one level. This happens below.
1668 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001669
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001670#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001671 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001672 /* Level is an indefinite-length array/map. */
1673
1674 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001675 bool bIsBreak = false;
1676 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1677 if(uReturn != QCBOR_SUCCESS) {
1678 goto Done;
1679 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001680
1681 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001682 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001683 break;
1684 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001685
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001686 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001687 * it is time to ascend one level.
1688 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001689
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001690#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001691 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001692
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001693
1694 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001695
Laurence Lundblade93d89472020-10-03 22:30:50 -07001696 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001697 * QCBORDecode_ExitBoundedMode().
1698 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001699 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001700 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001701 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001702 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001703 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001704 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001705
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001706 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001707 break;
1708 }
1709
1710 /* Finally, actually ascend one level. */
1711 DecodeNesting_Ascend(&(pMe->nesting));
1712 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001713
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001714 uReturn = QCBOR_SUCCESS;
1715
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001716#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001717Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001718#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1719
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001720 return uReturn;
1721}
1722
1723
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001724/**
1725 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1726 *
1727 * @param[in] pMe Decoder context
1728 * @param[out] pDecodedItem The decoded item that work is done on.
1729 *
1730 * @retval QCBOR_ERR_UNSUPPORTED
1731 * @retval QCBOR_ERR_HIT_END
1732 * @retval QCBOR_ERR_INT_OVERFLOW
1733 * @retval QCBOR_ERR_STRING_ALLOCATE
1734 * @retval QCBOR_ERR_STRING_TOO_LONG
1735 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1736 * @retval QCBOR_ERR_BAD_TYPE_7
1737 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1738 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1739 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1740 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1741 * @retval QCBOR_ERR_TOO_MANY_TAGS
1742 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1743 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1744 * @retval QCBOR_ERR_NO_MORE_ITEMS
1745 * @retval QCBOR_ERR_BAD_BREAK
1746 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1747 *
1748 * This handles the traversal descending into and asecnding out of
1749 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1750 * definite- and indefinte-length maps and arrays by looking at the
1751 * item count or finding CBOR breaks. It detects the ends of the
1752 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001753 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001754static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001755QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001756{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001757 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001758 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001759
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001760 /* If out of bytes to consume, it is either the end of the
1761 * top-level sequence of some bstr-wrapped CBOR that was entered.
1762 *
1763 * In the case of bstr-wrapped CBOR, the length of the
1764 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1765 * the bstr-wrapped CBOR is exited, the length is set back to the
1766 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001767 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001768 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001769 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001770 goto Done;
1771 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001772
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001773 /* Check to see if at the end of a bounded definite-length map or
1774 * array. The check for a break ending indefinite-length array is
1775 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001776 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001777 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001778 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001779 goto Done;
1780 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001781
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001782 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001783 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001784 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1785 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001786 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001787 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301788
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001789 /* Breaks ending arrays/maps are processed later in the call to
1790 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001791 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301792 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001793 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301794 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301795 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001796
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001797 /* Record the nesting level for this data item before processing
1798 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001799 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001800 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001801
Laurence Lundblade642282a2020-06-23 12:00:33 -07001802
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001803 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001804 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001805 /* If the new item is a map or array, descend.
1806 *
1807 * Empty indefinite-length maps and arrays are descended into,
1808 * but then ascended out of in the next chunk of code.
1809 *
1810 * Maps and arrays do count as items in the map/array that
1811 * encloses them so a decrement needs to be done for them too,
1812 * but that is done only when all the items in them have been
1813 * processed, not when they are opened with the exception of an
1814 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001815 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001816 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001817 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001818 pDecodedItem->uDataType,
1819 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001820 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001821 /* This error is probably a traversal error and it overrides
1822 * the non-traversal error.
1823 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001824 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001825 goto Done;
1826 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001827 }
1828
Laurence Lundblade02625d42020-06-25 14:41:41 -07001829 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1830 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1831 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001832 /* The following cases are handled here:
1833 * - A non-aggregate item like an integer or string
1834 * - An empty definite-length map or array
1835 * - An indefinite-length map or array that might be empty or might not.
1836 *
1837 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1838 * for an definite-length map/array and break detection for an
1839 * indefinite-0length map/array. If the end of the map/array was
1840 * reached, then it ascends nesting levels, possibly all the way
1841 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001842 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001843 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001844 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001845 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001846 /* This error is probably a traversal error and it overrides
1847 * the non-traversal error.
1848 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001849 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001850 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001851 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301852 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001853
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001854 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001855 /* Tell the caller what level is next. This tells them what
1856 * maps/arrays were closed out and makes it possible for them to
1857 * reconstruct the tree with just the information returned in a
1858 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001859 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001860 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001861 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001862 pDecodedItem->uNextNestLevel = 0;
1863 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001864 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001865 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001867Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001868 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001869}
1870
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001871
1872/**
1873 * @brief Shift 0th tag out of the tag list.
1874 *
1875 * pDecodedItem[in,out] The data item to convert.
1876 *
1877 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1878 * shifted into empty slot at the end of the tag list.
1879 */
1880static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001881{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001882 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1883 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1884 }
1885 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001886}
1887
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001888
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001889/**
1890 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1891 *
1892 * pDecodedItem[in,out] The data item to convert.
1893 *
1894 * @retval QCBOR_ERR_DATE_OVERFLOW
1895 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1896 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1897 *
1898 * The epoch date tag defined in QCBOR allows for floating-point
1899 * dates. It even allows a protocol to flop between date formats when
1900 * ever it wants. Floating-point dates aren't that useful as they are
1901 * only needed for dates beyond the age of the earth.
1902 *
1903 * This converts all the date formats into one format of an unsigned
1904 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001905 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001906static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001907{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001908 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001909
1910 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1911
1912 switch (pDecodedItem->uDataType) {
1913
1914 case QCBOR_TYPE_INT64:
1915 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1916 break;
1917
1918 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001919 /* This only happens for CBOR type 0 > INT64_MAX so it is
1920 * always an overflow.
1921 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001922 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1923 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001924 break;
1925
1926 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001927 case QCBOR_TYPE_FLOAT:
1928#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001929 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001930 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001931 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001932 pDecodedItem->val.dfnum :
1933 (double)pDecodedItem->val.fnum;
1934
1935 /* The conversion from float to integer requires overflow
1936 * detection since floats can be much larger than integers.
1937 * This implementation errors out on these large float values
1938 * since they are beyond the age of the earth.
1939 *
1940 * These constants for the overflow check are computed by the
1941 * compiler. They are not computed at run time.
1942 *
1943 * The factor of 0x7ff is added/subtracted to avoid a
1944 * rounding error in the wrong direction when the compiler
1945 * computes these constants. There is rounding because an
1946 * 64-bit integer has 63 bits of precision where a double
1947 * only has 53 bits. Without the 0x7ff factor, the compiler
1948 * may round up and produce a double for the bounds check
1949 * that is larger than can be stored in a 64-bit integer. The
1950 * amount of 0x7ff is picked because it has 11 bits set.
1951 *
1952 * Without the 0x7ff there is a ~30 minute range of time
1953 * values 10 billion years in the past and in the future
1954 * where this code could go wrong. Some compilers correctly
1955 * generate a warning or error without the 0x7ff.
1956 */
1957 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1958 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1959
1960 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001961 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 goto Done;
1963 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001964
1965 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001967 pDecodedItem->val.epochDate.fSecondsFraction =
1968 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001969 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001970#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001971
Laurence Lundbladec7114722020-08-13 05:11:40 -07001972 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001973 goto Done;
1974
Laurence Lundblade9682a532020-06-06 18:33:04 -07001975#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976 break;
1977
1978 default:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001979 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001980 goto Done;
1981 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001982
Laurence Lundblade59289e52019-12-30 13:44:37 -08001983 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1984
1985Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001986 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001987}
1988
1989
Laurence Lundblade208700a2021-05-13 01:22:11 -07001990/**
1991 * @brief Convert the days epoch date
Laurence Lundblade58541fe2021-05-07 01:24:49 -07001992 *
1993 * pDecodedItem[in,out] The data item to convert.
1994 *
1995 * @retval QCBOR_ERR_DATE_OVERFLOW
1996 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1997 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1998 *
Laurence Lundblade208700a2021-05-13 01:22:11 -07001999 * This is much simpler than the other epoch date format because
2000 * floating-porint is not allowed. It is mostly a simple type check.
Laurence Lundblade58541fe2021-05-07 01:24:49 -07002001 */
2002static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2003{
2004 QCBORError uReturn = QCBOR_SUCCESS;
2005
2006 switch (pDecodedItem->uDataType) {
2007
2008 case QCBOR_TYPE_INT64:
2009 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2010 break;
2011
2012 case QCBOR_TYPE_UINT64:
2013 /* This only happens for CBOR type 0 > INT64_MAX so it is
2014 * always an overflow.
2015 */
2016 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2017 goto Done;
2018 break;
2019
2020 default:
2021 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
2022 goto Done;
Laurence Lundblade208700a2021-05-13 01:22:11 -07002023 break;
Laurence Lundblade58541fe2021-05-07 01:24:49 -07002024 }
2025
2026 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2027
2028Done:
2029 return uReturn;
2030}
2031
2032
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002033#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002034/**
2035 * @brief Decode decimal fractions and big floats.
2036 *
2037 * @param[in] pMe The decode context.
2038 * @param[in,out] pDecodedItem On input the array data item that
2039 * holds the mantissa and exponent. On
2040 * output the decoded mantissa and
2041 * exponent.
2042 *
2043 * @returns Decoding errors from getting primitive data items or
2044 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2045 *
2046 * When called pDecodedItem must be the array that is tagged as a big
2047 * float or decimal fraction, the array that has the two members, the
2048 * exponent and mantissa.
2049 *
2050 * This will fetch and decode the exponent and mantissa and put the
2051 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002053static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002054QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002055{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002056 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002057
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002058 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002060 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002061 goto Done;
2062 }
2063
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002064 /* A check for pDecodedItem->val.uCount == 2 would work for
2065 * definite-length arrays, but not for indefnite. Instead remember
2066 * the nesting level the two integers must be at, which is one
2067 * deeper than that of the array.
2068 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002069 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2070
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002071 /* --- Which is it, decimal fraction or a bigfloat? --- */
2072 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2074
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002075 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002077 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2078 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002079 goto Done;
2080 }
2081 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002082 /* Array is empty or a map/array encountered when expecting an int */
2083 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002084 goto Done;
2085 }
2086 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002087 /* Data arriving as an unsigned int < INT64_MAX has been
2088 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2089 * also means that the only data arriving here of type
2090 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2091 * and thus an error that will get handled in the next else.
2092 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002093 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2094 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002095 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2096 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097 goto Done;
2098 }
2099
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002100 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002101 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002102 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2103 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002104 goto Done;
2105 }
2106 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002107 /* Mantissa missing or map/array encountered when expecting number */
2108 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002109 goto Done;
2110 }
2111 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002112 /* Data arriving as an unsigned int < INT64_MAX has been
2113 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2114 * also means that the only data arriving here of type
2115 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2116 * and thus an error that will get handled in an else below.
2117 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002118 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002119 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2120 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002121 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002123 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002124 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2125 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2126 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002127 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002128 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2129 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002130 goto Done;
2131 }
2132
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002133 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002134 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002135 /* Extra items in the decimal fraction / big float */
2136 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002137 goto Done;
2138 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002139 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002140
2141Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002142 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002143}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002144#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002145
2146
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002147#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002148/**
2149 * @brief Decode the MIME type tag
2150 *
2151 * @param[in,out] pDecodedItem The item to decode.
2152 *
2153 * Handle the text and binary MIME type tags. Slightly too complicated
2154 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2155 * incorreclty text-only.
2156 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002157static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002158{
2159 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2160 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002161 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002162 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2163 } else {
2164 return QCBOR_ERR_BAD_OPT_TAG;
2165 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002166
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002167 return QCBOR_SUCCESS;
2168}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002169#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002170
2171
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002172/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002173 * Table of CBOR tags whose content is either a text string or a byte
2174 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2175 * of uQCBORtype indicates the content should be a byte string rather
2176 * than a text string
2177 */
2178struct StringTagMapEntry {
2179 uint16_t uTagNumber;
2180 uint8_t uQCBORtype;
2181};
2182
2183#define IS_BYTE_STRING_BIT 0x80
2184#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2185
2186static const struct StringTagMapEntry StringTagMap[] = {
2187 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade58541fe2021-05-07 01:24:49 -07002188 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
2189
Laurence Lundblade99615302020-11-29 11:19:47 -08002190 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2191 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2192 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2193 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002194#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002195 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2196 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2197 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2198 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002199#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002200 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2201 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2202};
2203
2204
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002205/**
2206 * @brief Process standard CBOR tags whose content is a string
2207 *
2208 * @param[in] uTag The tag.
2209 * @param[in,out] pDecodedItem The data item.
2210 *
2211 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2212 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2213 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2214 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002215 * Process the CBOR tags that whose content is a byte string or a text
2216 * string and for which the string is just passed on to the caller.
2217 *
2218 * This maps the CBOR tag to the QCBOR type and checks the content
2219 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002220 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002221 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002222 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002223static inline QCBORError
2224ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002225{
Laurence Lundblade99615302020-11-29 11:19:47 -08002226 /* This only works on tags that were not mapped; no need for other yet */
2227 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2228 return QCBOR_ERR_UNSUPPORTED;
2229 }
2230
2231 unsigned uIndex;
2232 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2233 if(StringTagMap[uIndex].uTagNumber == uTag) {
2234 break;
2235 }
2236 }
2237
2238 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2239 if(uQCBORType == QCBOR_TYPE_NONE) {
2240 /* repurpose this error to mean, not handled here */
2241 return QCBOR_ERR_UNSUPPORTED;
2242 }
2243
2244 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2245 if(uQCBORType & IS_BYTE_STRING_BIT) {
2246 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2247 }
2248
2249 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002250 return QCBOR_ERR_BAD_OPT_TAG;
2251 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002252
Laurence Lundblade99615302020-11-29 11:19:47 -08002253 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002254 return QCBOR_SUCCESS;
2255}
2256
2257
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002258/**
2259 * @brief Decode tag content for select tags (decoding layer 1).
2260 *
2261 * @param[in] pMe The decode context.
2262 * @param[out] pDecodedItem The decoded item.
2263 *
2264 * @return Decoding error code.
2265 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002266 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2267 * but the whole tag was not decoded. Here, the whole tags (tag number
2268 * and tag content) that are supported by QCBOR are decoded. This is a
2269 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002270 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002271static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002272QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002273{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002274 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002275
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002276 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002277 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002278 goto Done;
2279 }
2280
Laurence Lundblade99615302020-11-29 11:19:47 -08002281 /* When there are no tag numbers for the item, this exits first
2282 * thing and effectively does nothing.
2283 *
2284 * This loops over all the tag numbers accumulated for this item
2285 * trying to decode and interpret them. This stops at the end of
2286 * the list or at the first tag number that can't be interpreted by
2287 * this code. This is effectively a recursive processing of the
2288 * tags number list that handles nested tags.
2289 */
2290 while(1) {
2291 /* Don't bother to unmap tags via QCBORITem.uTags since this
2292 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2293 */
2294 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002295
Laurence Lundblade99615302020-11-29 11:19:47 -08002296 if(uTagToProcess == CBOR_TAG_INVALID16) {
2297 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002298 break;
2299
Laurence Lundblade99615302020-11-29 11:19:47 -08002300 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002301 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002302
Laurence Lundblade58541fe2021-05-07 01:24:49 -07002303 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2304 uReturn = DecodeDaysEpoch(pDecodedItem);
2305
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002306#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002307 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2308 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002309 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002310#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002311#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002312 } else if(uTagToProcess == CBOR_TAG_MIME ||
2313 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002314 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002315#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002316
Laurence Lundblade99615302020-11-29 11:19:47 -08002317 } else {
2318 /* See if it is a pass-through byte/text string tag; process if so */
2319 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002320
Laurence Lundblade99615302020-11-29 11:19:47 -08002321 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2322 /* It wasn't a pass-through byte/text string tag so it is
2323 * an unknown tag. This is the exit from the loop on the
2324 * first unknown tag. It is a successful exit.
2325 */
2326 uReturn = QCBOR_SUCCESS;
2327 break;
2328 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002329 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002330
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002331 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002332 /* Error exit from the loop */
2333 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002334 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002335
2336 /* A tag was successfully processed, shift it out of the list of
2337 * tags returned. This is the loop increment.
2338 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002339 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002340 }
2341
2342Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002343 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002344}
2345
2346
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002347/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002348 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002349 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002350QCBORError
2351QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2352{
2353 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002354 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002355 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002356 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2357 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2358 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002359 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002360}
2361
2362
2363/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002364 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002365 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002366QCBORError
2367QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2368{
2369 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2370 const UsefulInputBuf Save = pMe->InBuf;
2371
2372 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2373
2374 pMe->nesting = SaveNesting;
2375 pMe->InBuf = Save;
2376
2377 return uErr;
2378}
2379
2380
2381/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002382 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002383 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002384void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2385{
2386 if(pMe->uLastError != QCBOR_SUCCESS) {
2387 return;
2388 }
2389
2390 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2391}
2392
2393
2394/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002395 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002396 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002397QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002398QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2399 QCBORItem *pDecodedItem,
2400 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002401{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002402 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002403
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002404 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2405 if(uReturn != QCBOR_SUCCESS) {
2406 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002407 }
2408
2409 if(pTags != NULL) {
2410 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002411 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002412 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2413 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002414 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002415 }
2416 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2417 return QCBOR_ERR_TOO_MANY_TAGS;
2418 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002419 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002420 pTags->uNumUsed++;
2421 }
2422 }
2423
2424 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002425}
2426
2427
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002428/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002429 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302430 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002431bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002432 const QCBORItem *pItem,
2433 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002434{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002435 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2436 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002437 break;
2438 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002439 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002440 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002441 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002442 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002443
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002444 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002445}
2446
2447
2448/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002449 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002450 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002451QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002452{
Laurence Lundblade87495732021-02-26 10:05:55 -07002453 if(puConsumed != NULL) {
2454 *puConsumed = pMe->InBuf.cursor;
2455 }
2456
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002457 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002458
2459 if(uReturn != QCBOR_SUCCESS) {
2460 goto Done;
2461 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002462
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002463 /* Error out if all the maps/arrays are not closed out */
2464 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002465 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002466 goto Done;
2467 }
2468
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002469 /* Error out if not all the bytes are consumed */
2470 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002471 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002472 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002473
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002474Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002475 return uReturn;
2476}
2477
2478
2479/*
2480 * Public function, see header qcbor/qcbor_decode.h file
2481 */
2482QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2483{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002484#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002485 /* Call the destructor for the string allocator if there is one.
2486 * Always called, even if there are errors; always have to clean up.
2487 */
2488 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002489#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002490
Laurence Lundblade87495732021-02-26 10:05:55 -07002491 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002492}
2493
2494
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002495/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002496 * Public function, see header qcbor/qcbor_decode.h file
2497 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002498// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002499uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2500 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002501 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002502{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002503 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2504 return CBOR_TAG_INVALID64;
2505 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002506 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2507 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002508 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002509 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002510 }
2511}
2512
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002513
Laurence Lundblade9b334962020-08-27 10:55:53 -07002514/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002515 * Public function, see header qcbor/qcbor_decode.h file
2516 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002517uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2518 uint32_t uIndex)
2519{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002520 if(pMe->uLastError != QCBOR_SUCCESS) {
2521 return CBOR_TAG_INVALID64;
2522 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002523 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2524 return CBOR_TAG_INVALID64;
2525 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002526 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002527 }
2528}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002529
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002530
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002531
2532
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002533#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002534
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002535/* ===========================================================================
2536 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002538 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002539 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2540 implements the function type QCBORStringAllocate and allows easy
2541 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002542
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002543 This particular allocator is built-in for convenience. The caller
2544 can implement their own. All of this following code will get
2545 dead-stripped if QCBORDecode_SetMemPool() is not called.
2546
2547 This is a very primitive memory allocator. It does not track
2548 individual allocations, only a high-water mark. A free or
2549 reallocation must be of the last chunk allocated.
2550
2551 The size of the pool and offset to free memory are packed into the
2552 first 8 bytes of the memory pool so we don't have to keep them in
2553 the decode context. Since the address of the pool may not be
2554 aligned, they have to be packed and unpacked as if they were
2555 serialized data of the wire or such.
2556
2557 The sizes packed in are uint32_t to be the same on all CPU types
2558 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002559 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002560
2561
Laurence Lundbladeee851742020-01-08 08:37:05 -08002562static inline int
2563MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002564{
2565 // Use of UsefulInputBuf is overkill, but it is convenient.
2566 UsefulInputBuf UIB;
2567
Laurence Lundbladeee851742020-01-08 08:37:05 -08002568 // Just assume the size here. It was checked during SetUp so
2569 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002570 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002571 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2572 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2573 return UsefulInputBuf_GetError(&UIB);
2574}
2575
2576
Laurence Lundbladeee851742020-01-08 08:37:05 -08002577static inline int
2578MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002579{
2580 // Use of UsefulOutBuf is overkill, but convenient. The
2581 // length check performed here is useful.
2582 UsefulOutBuf UOB;
2583
2584 UsefulOutBuf_Init(&UOB, Pool);
2585 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2586 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2587 return UsefulOutBuf_GetError(&UOB);
2588}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002589
2590
2591/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002592 Internal function for an allocation, reallocation free and destuct.
2593
2594 Having only one function rather than one each per mode saves space in
2595 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002596
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002597 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2598 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002599static UsefulBuf
2600MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002601{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002602 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002603
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002604 uint32_t uPoolSize;
2605 uint32_t uFreeOffset;
2606
2607 if(uNewSize > UINT32_MAX) {
2608 // This allocator is only good up to 4GB. This check should
2609 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2610 goto Done;
2611 }
2612 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2613
2614 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2615 goto Done;
2616 }
2617
2618 if(uNewSize) {
2619 if(pMem) {
2620 // REALLOCATION MODE
2621 // Calculate pointer to the end of the memory pool. It is
2622 // assumed that pPool + uPoolSize won't wrap around by
2623 // assuming the caller won't pass a pool buffer in that is
2624 // not in legitimate memory space.
2625 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2626
2627 // Check that the pointer for reallocation is in the range of the
2628 // pool. This also makes sure that pointer math further down
2629 // doesn't wrap under or over.
2630 if(pMem >= pPool && pMem < pPoolEnd) {
2631 // Offset to start of chunk for reallocation. This won't
2632 // wrap under because of check that pMem >= pPool. Cast
2633 // is safe because the pool is always less than UINT32_MAX
2634 // because of check in QCBORDecode_SetMemPool().
2635 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2636
2637 // Check to see if the allocation will fit. uPoolSize -
2638 // uMemOffset will not wrap under because of check that
2639 // pMem is in the range of the uPoolSize by check above.
2640 if(uNewSize <= uPoolSize - uMemOffset) {
2641 ReturnValue.ptr = pMem;
2642 ReturnValue.len = uNewSize;
2643
2644 // Addition won't wrap around over because uNewSize was
2645 // checked to be sure it is less than the pool size.
2646 uFreeOffset = uMemOffset + uNewSize32;
2647 }
2648 }
2649 } else {
2650 // ALLOCATION MODE
2651 // uPoolSize - uFreeOffset will not underflow because this
2652 // pool implementation makes sure uFreeOffset is always
2653 // smaller than uPoolSize through this check here and
2654 // reallocation case.
2655 if(uNewSize <= uPoolSize - uFreeOffset) {
2656 ReturnValue.len = uNewSize;
2657 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002658 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002659 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002660 }
2661 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002662 if(pMem) {
2663 // FREE MODE
2664 // Cast is safe because of limit on pool size in
2665 // QCBORDecode_SetMemPool()
2666 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2667 } else {
2668 // DESTRUCT MODE
2669 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002670 }
2671 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002672
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002673 UsefulBuf Pool = {pPool, uPoolSize};
2674 MemPool_Pack(Pool, uFreeOffset);
2675
2676Done:
2677 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002678}
2679
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002680
Laurence Lundbladef6531662018-12-04 10:42:22 +09002681/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002682 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002683 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002684QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2685 UsefulBuf Pool,
2686 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002687{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002688 // The pool size and free mem offset are packed into the beginning
2689 // of the pool memory. This compile time check make sure the
2690 // constant in the header is correct. This check should optimize
2691 // down to nothing.
2692 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002693 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002694 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002695
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002696 // The pool size and free offset packed in to the beginning of pool
2697 // memory are only 32-bits. This check will optimize out on 32-bit
2698 // machines.
2699 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002700 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002701 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002702
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002703 // This checks that the pool buffer given is big enough.
2704 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002705 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002707
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002708 pMe->StringAllocator.pfAllocator = MemPool_Function;
2709 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2710 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002711
Laurence Lundblade30816f22018-11-10 13:40:22 +07002712 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002713}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002714#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002715
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002716
2717
Laurence Lundblade9b334962020-08-27 10:55:53 -07002718static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2719{
2720 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2721}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002722
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002723
2724/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002725 Consume an entire map or array (and do next to
2726 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002727 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002728static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002729ConsumeItem(QCBORDecodeContext *pMe,
2730 const QCBORItem *pItemToConsume,
2731 uint_fast8_t *puNextNestLevel)
2732{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002733 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002734 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002735
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002736 // If it is a map or array, this will tell if it is empty.
2737 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2738
2739 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2740 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002742 /* This works for definite- and indefinite- length
Laurence Lundblade1341c592020-04-11 14:19:05 -07002743 * maps and arrays by using the nesting level
2744 */
2745 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002746 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002747 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748 goto Done;
2749 }
2750 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002751
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002752 *puNextNestLevel = Item.uNextNestLevel;
2753
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002754 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002755
Laurence Lundblade1341c592020-04-11 14:19:05 -07002756 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002757 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002758 /* Just pass the nesting level through */
2759 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2760
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002761 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002762 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002763
2764Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002765 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002766}
2767
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002768
2769void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2770{
2771 uint8_t uNextNestLevel;
2772
2773 QCBORDecode_VGetNext(pMe, pDecodedItem);
2774
2775 if(pMe->uLastError == QCBOR_SUCCESS) {
2776 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem, &uNextNestLevel);
2777 pDecodedItem->uNextNestLevel = uNextNestLevel;
2778 }
2779}
2780
2781
2782
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002783/* Call only on maps and arrays. Rewinds the cursor
2784 * to the start as if it was just entered.
2785 */
2786static void RewindMapOrArray(QCBORDecodeContext *pMe)
2787{
2788 /* Reset nesting tracking to the deepest bounded level */
2789 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2790
2791 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2792
2793 /* Reposition traversal cursor to the start of the map/array */
2794 UsefulInputBuf_Seek(&(pMe->InBuf),
2795 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2796}
2797
2798
2799/*
2800 Public function, see header qcbor/qcbor_decode.h file
2801 */
2802void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2803{
2804 if(pMe->nesting.pCurrentBounded != NULL) {
2805 /* In a bounded map, array or bstr-wrapped CBOR */
2806
2807 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2808 /* In bstr-wrapped CBOR. */
2809
2810 /* Reposition traversal cursor to start of wrapping byte string */
2811 UsefulInputBuf_Seek(&(pMe->InBuf),
2812 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2813 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2814
2815 } else {
2816 /* In a map or array */
2817 RewindMapOrArray(pMe);
2818 }
2819
2820 } else {
2821 /* Not in anything bounded */
2822
2823 /* Reposition traversal cursor to the start of input CBOR */
2824 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2825
2826 /* Reset nesting tracking to beginning of input. */
2827 DecodeNesting_Init(&(pMe->nesting));
2828 }
2829
2830 pMe->uLastError = QCBOR_SUCCESS;
2831}
2832
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002833
Laurence Lundblade1341c592020-04-11 14:19:05 -07002834/* Return true if the labels in Item1 and Item2 are the same.
2835 Works only for integer and string labels. Returns false
2836 for any other type. */
2837static inline bool
2838MatchLabel(QCBORItem Item1, QCBORItem Item2)
2839{
2840 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2841 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2842 return true;
2843 }
2844 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002845 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002846 return true;
2847 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002848 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002849 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2850 return true;
2851 }
2852 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2853 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2854 return true;
2855 }
2856 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002857
Laurence Lundblade1341c592020-04-11 14:19:05 -07002858 /* Other label types are never matched */
2859 return false;
2860}
2861
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002862
2863/*
2864 Returns true if Item1 and Item2 are the same type
2865 or if either are of QCBOR_TYPE_ANY.
2866 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002867static inline bool
2868MatchType(QCBORItem Item1, QCBORItem Item2)
2869{
2870 if(Item1.uDataType == Item2.uDataType) {
2871 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002872 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002873 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002874 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002875 return true;
2876 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002877 return false;
2878}
2879
2880
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002881/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002882 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002883
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002884 @param[in] pMe The decode context to search.
2885 @param[in,out] pItemArray The items to search for and the items found.
2886 @param[out] puOffset Byte offset of last item matched.
2887 @param[in] pCBContext Context for the not-found item call back.
2888 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002889
2890 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2891
Laurence Lundblade93d89472020-10-03 22:30:50 -07002892 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2893 were found for one of the labels being
2894 search for. This duplicate detection is
2895 only performed for items in pItemArray,
2896 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002897
Laurence Lundblade93d89472020-10-03 22:30:50 -07002898 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2899 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002900
2901 @retval Also errors returned by QCBORDecode_GetNext().
2902
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002903 On input pItemArray contains a list of labels and data types
2904 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002905
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002906 On output the fully retrieved items are filled in with
2907 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002908
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002909 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002910
2911 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002912 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002913static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002914MapSearch(QCBORDecodeContext *pMe,
2915 QCBORItem *pItemArray,
2916 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002917 void *pCBContext,
2918 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002919{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002920 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002921 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002922
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002923 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002924 uReturn = pMe->uLastError;
2925 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002926 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002927
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002928 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002929 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2930 /* QCBOR_TYPE_NONE as first item indicates just looking
2931 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002932 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2933 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002934 }
2935
Laurence Lundblade085d7952020-07-24 10:26:30 -07002936 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2937 // It is an empty bounded array or map
2938 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2939 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002940 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002941 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002942 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002943 // Nothing is ever found in an empty array or map. All items
2944 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002945 uReturn = QCBOR_SUCCESS;
2946 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002947 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002948 }
2949
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002950 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002951 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2952
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002953 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002954 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002955
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002956 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002957 Loop over all the items in the map or array. Each item
2958 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002959 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002960 length maps and arrays. The only reason this is ever
2961 called on arrays is to find their end position.
2962
2963 This will always run over all items in order to do
2964 duplicate detection.
2965
2966 This will exit with failure if it encounters an
2967 unrecoverable error, but continue on for recoverable
2968 errors.
2969
2970 If a recoverable error occurs on a matched item, then
2971 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002972 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002973 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002974 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002975 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002976 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002977 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002978
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002979 /* Get the item */
2980 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002981 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002982 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002983 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002984 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002985 goto Done;
2986 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002987 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002988 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002989 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002990 goto Done;
2991 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002992
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002993 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002994 bool bMatched = false;
2995 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2996 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002997 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002998 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2999 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003000 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003001 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003002 if(uResult != QCBOR_SUCCESS) {
3003 /* The label matches, but the data item is in error */
3004 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003005 goto Done;
3006 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003007 if(!MatchType(Item, pItemArray[nIndex])) {
3008 /* The data item is not of the type(s) requested */
3009 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003010 goto Done;
3011 }
3012
Laurence Lundblade1341c592020-04-11 14:19:05 -07003013 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003014 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003015 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003016 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003017 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003018 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003019 bMatched = true;
3020 }
3021 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003022
3023
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003024 if(!bMatched && pfCallback != NULL) {
3025 /*
3026 Call the callback on unmatched labels.
3027 (It is tempting to do duplicate detection here, but that would
3028 require dynamic memory allocation because the number of labels
3029 that might be encountered is unbounded.)
3030 */
3031 uReturn = (*pfCallback)(pCBContext, &Item);
3032 if(uReturn != QCBOR_SUCCESS) {
3033 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003034 }
3035 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003036
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003037 /*
3038 Consume the item whether matched or not. This
3039 does the work of traversing maps and array and
3040 everything in them. In this loop only the
3041 items at the current nesting level are examined
3042 to match the labels.
3043 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003044 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003045 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046 goto Done;
3047 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003048
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003049 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003051 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003052
3053 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003054
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003055 // Check here makes sure that this won't accidentally be
3056 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003057 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003058 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3059 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003060 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3061 goto Done;
3062 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003063 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3064 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003065
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003066 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003067 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3068
3069 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003070 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003071 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003072 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003073 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3074 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003075 }
3076 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003077
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003078 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003079}
3080
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003081
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003083 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003084*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003085void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3086 int64_t nLabel,
3087 uint8_t uQcborType,
3088 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003089{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003090 if(pMe->uLastError != QCBOR_SUCCESS) {
3091 return;
3092 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003093
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003094 QCBORItem OneItemSeach[2];
3095 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3096 OneItemSeach[0].label.int64 = nLabel;
3097 OneItemSeach[0].uDataType = uQcborType;
3098 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003099
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003100 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003101
3102 *pItem = OneItemSeach[0];
3103
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003104 if(uReturn != QCBOR_SUCCESS) {
3105 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003106 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003107 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003108 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003109 }
3110
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003111 Done:
3112 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003113}
3114
3115
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003116/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003117 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003118*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003119void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3120 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003121 uint8_t uQcborType,
3122 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003123{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003124 if(pMe->uLastError != QCBOR_SUCCESS) {
3125 return;
3126 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003127
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003128 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003129 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3130 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3131 OneItemSeach[0].uDataType = uQcborType;
3132 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003133
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003134 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3135 if(uReturn != QCBOR_SUCCESS) {
3136 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003137 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003138 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003139 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003140 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003141 }
3142
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003143 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003144
3145Done:
3146 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003147}
3148
3149
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003150
Laurence Lundblade93d89472020-10-03 22:30:50 -07003151static QCBORError
3152CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003153{
3154 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3155 if(uDataType == puTypeList[i]) {
3156 return QCBOR_SUCCESS;
3157 }
3158 }
3159 return QCBOR_ERR_UNEXPECTED_TYPE;
3160}
3161
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003162
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003163/**
3164 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003165 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003166
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003167 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3168 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003169
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003170 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3171 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003172 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003173static QCBORError
3174CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003175{
3176 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3177 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3178 /* There are tags that QCBOR couldn't process on this item and
3179 the caller has told us there should not be. */
3180 return QCBOR_ERR_UNEXPECTED_TYPE;
3181 }
3182
3183 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3184 const int nItemType = pItem->uDataType;
3185
3186 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3187 // Must match the tag and only the tag
3188 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3189 }
3190
3191 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3192 if(uReturn == QCBOR_SUCCESS) {
3193 return QCBOR_SUCCESS;
3194 }
3195
3196 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3197 /* Must match the content type and only the content type.
3198 There was no match just above so it is a fail. */
3199 return QCBOR_ERR_UNEXPECTED_TYPE;
3200 }
3201
3202 /* If here it can match either the tag or the content
3203 and it hasn't matched the content, so the end
3204 result is whether it matches the tag. This is
3205 also the case that the CBOR standard discourages. */
3206
3207 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3208}
3209
Laurence Lundblade9b334962020-08-27 10:55:53 -07003210
Laurence Lundblade9b334962020-08-27 10:55:53 -07003211
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003212// This could be semi-private if need be
3213static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003214void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3215 int64_t nLabel,
3216 TagSpecification TagSpec,
3217 QCBORItem *pItem)
3218{
3219 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3220 if(pMe->uLastError != QCBOR_SUCCESS) {
3221 return;
3222 }
3223
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003224 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003225}
3226
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003227
3228// This could be semi-private if need be
3229static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003230void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3231 const char *szLabel,
3232 TagSpecification TagSpec,
3233 QCBORItem *pItem)
3234{
3235 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3236 if(pMe->uLastError != QCBOR_SUCCESS) {
3237 return;
3238 }
3239
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003240 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003241}
3242
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003243// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003244void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3245 int64_t nLabel,
3246 TagSpecification TagSpec,
3247 UsefulBufC *pString)
3248{
3249 QCBORItem Item;
3250 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3251 if(pMe->uLastError == QCBOR_SUCCESS) {
3252 *pString = Item.val.string;
3253 }
3254}
3255
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003256// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003257void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3258 const char * szLabel,
3259 TagSpecification TagSpec,
3260 UsefulBufC *pString)
3261{
3262 QCBORItem Item;
3263 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3264 if(pMe->uLastError == QCBOR_SUCCESS) {
3265 *pString = Item.val.string;
3266 }
3267}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003268
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003269/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003270 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003271*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003272void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003273{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003274 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3275 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003276}
3277
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003278/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003279 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003280*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003281void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3282 QCBORItem *pItemList,
3283 void *pCallbackCtx,
3284 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003285{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003286 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3287 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003288}
3289
3290
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003291/**
3292 * @brief Search for a map/array by label and enter it
3293 *
3294 * @param[in] pMe The decode context.
3295 * @param[in] pSearch The map/array to search for.
3296 *
3297 * @c pSearch is expected to contain one item of type map or array
3298 * with the label specified. The current bounded map will be searched for
3299 * this and if found will be entered.
3300 *
3301 * If the label is not found, or the item found is not a map or array,
3302 * the error state is set.
3303 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003304static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003305{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003306 // The first item in pSearch is the one that is to be
3307 // entered. It should be the only one filled in. Any other
3308 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003309 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003310 return;
3311 }
3312
3313 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003314 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003315 if(pMe->uLastError != QCBOR_SUCCESS) {
3316 return;
3317 }
3318
Laurence Lundblade9b334962020-08-27 10:55:53 -07003319 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003320 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003321 return;
3322 }
3323
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003324
3325 /* The map or array was found. Now enter it.
3326 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003327 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3328 * next item for the pre-order traversal cursor to be the map/array
3329 * found by MapSearch(). The next few lines of code force the
3330 * cursor to that.
3331 *
3332 * There is no need to retain the old cursor because
3333 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3334 * beginning of the map/array being entered.
3335 *
3336 * The cursor is forced by: 1) setting the input buffer position to
3337 * the item offset found by MapSearch(), 2) setting the map/array
3338 * counter to the total in the map/array, 3) setting the nesting
3339 * level. Setting the map/array counter to the total is not
3340 * strictly correct, but this is OK because this cursor only needs
3341 * to be used to get one item and MapSearch() has already found it
3342 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003343 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003344 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003345
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003346 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3347
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003348 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003349
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003350 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003351}
3352
3353
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003354/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003355 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003356*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003357void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003358{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003359 QCBORItem OneItemSeach[2];
3360 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3361 OneItemSeach[0].label.int64 = nLabel;
3362 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3363 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003364
Laurence Lundblade9b334962020-08-27 10:55:53 -07003365 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003366 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003367}
3368
3369
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003370/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003371 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003372*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003373void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003374{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003375 QCBORItem OneItemSeach[2];
3376 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3377 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3378 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3379 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003380
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003381 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003382}
3383
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003384/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003385 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003386*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003387void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003388{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003389 QCBORItem OneItemSeach[2];
3390 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3391 OneItemSeach[0].label.int64 = nLabel;
3392 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3393 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003394
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003395 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003396}
3397
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003398/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003399 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003400*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003401void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3402{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003403 QCBORItem OneItemSeach[2];
3404 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3405 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3406 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3407 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003408
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003409 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003410}
3411
3412
Laurence Lundblade02625d42020-06-25 14:41:41 -07003413// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003414void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003415{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003416 QCBORError uErr;
3417
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003418 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003419 if(pMe->uLastError != QCBOR_SUCCESS) {
3420 // Already in error state; do nothing.
3421 return;
3422 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003423
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003424 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003425 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003426 uErr = QCBORDecode_GetNext(pMe, &Item);
3427 if(uErr != QCBOR_SUCCESS) {
3428 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003429 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003430 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003431 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3432 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003433 }
3434
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003435 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003436
3437
Laurence Lundbladef0499502020-08-01 11:55:57 -07003438 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003439 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003440 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3441 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003442 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003443 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3444 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003445 // Special case to increment nesting level for zero-length maps
3446 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003447 DecodeNesting_Descend(&(pMe->nesting), uType);
3448 }
3449
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003450 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003451
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003452 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3453 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003454
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003455 if(pItem != NULL) {
3456 *pItem = Item;
3457 }
3458
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003459Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003460 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003461}
3462
Laurence Lundblade02625d42020-06-25 14:41:41 -07003463
3464/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003465 This is the common work for exiting a level that is a bounded map,
3466 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003467
3468 One chunk of work is to set up the pre-order traversal so it is at
3469 the item just after the bounded map, array or bstr that is being
3470 exited. This is somewhat complex.
3471
3472 The other work is to level-up the bounded mode to next higest bounded
3473 mode or the top level if there isn't one.
3474 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003475static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003476ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003477{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003478 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003479
Laurence Lundblade02625d42020-06-25 14:41:41 -07003480 /*
3481 First the pre-order-traversal byte offset is positioned to the
3482 item just after the bounded mode item that was just consumed.
3483 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003484 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3485
Laurence Lundblade02625d42020-06-25 14:41:41 -07003486 /*
3487 Next, set the current nesting level to one above the bounded level
3488 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003489
Laurence Lundblade02625d42020-06-25 14:41:41 -07003490 DecodeNesting_CheckBoundedType() is always called before this and
3491 makes sure pCurrentBounded is valid.
3492 */
3493 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3494
3495 /*
3496 This does the complex work of leveling up the pre-order traversal
3497 when the end of a map or array or another bounded level is
3498 reached. It may do nothing, or ascend all the way to the top
3499 level.
3500 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003501 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003502 if(uErr != QCBOR_SUCCESS) {
3503 goto Done;
3504 }
3505
Laurence Lundblade02625d42020-06-25 14:41:41 -07003506 /*
3507 This makes the next highest bounded level the current bounded
3508 level. If there is no next highest level, then no bounded mode is
3509 in effect.
3510 */
3511 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003512
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003513 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003514
3515Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003516 return uErr;
3517}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003518
Laurence Lundblade02625d42020-06-25 14:41:41 -07003519
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003520// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003521void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003522{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003523 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003524 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003525 return;
3526 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003527
Laurence Lundblade02625d42020-06-25 14:41:41 -07003528 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003529
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003530 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003531 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003532 goto Done;
3533 }
3534
Laurence Lundblade02625d42020-06-25 14:41:41 -07003535 /*
3536 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003537 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003538 from previous map search, then do a dummy search.
3539 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003540 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003541 QCBORItem Dummy;
3542 Dummy.uLabelType = QCBOR_TYPE_NONE;
3543 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3544 if(uErr != QCBOR_SUCCESS) {
3545 goto Done;
3546 }
3547 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003548
Laurence Lundblade02625d42020-06-25 14:41:41 -07003549 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003550
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003551Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003552 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003553}
3554
3555
Laurence Lundblade1341c592020-04-11 14:19:05 -07003556
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003557static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003558 const QCBORItem *pItem,
3559 uint8_t uTagRequirement,
3560 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003561{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003562 if(pBstr) {
3563 *pBstr = NULLUsefulBufC;
3564 }
3565
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003566 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003567 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003568 return pMe->uLastError;
3569 }
3570
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003571 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003572
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003573 const TagSpecification TagSpec =
3574 {
3575 uTagRequirement,
3576 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3577 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3578 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003579
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003580 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003581 if(uError != QCBOR_SUCCESS) {
3582 goto Done;
3583 }
3584
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003585 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003586 /* Reverse the decrement done by GetNext() for the bstr so the
3587 * increment in QCBORDecode_NestLevelAscender() called by
3588 * ExitBoundedLevel() will work right.
3589 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003590 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003591 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003592
3593 if(pBstr) {
3594 *pBstr = pItem->val.string;
3595 }
3596
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003597 /* This saves the current length of the UsefulInputBuf and then
3598 * narrows the UsefulInputBuf to start and length of the wrapped
3599 * CBOR that is being entered.
3600 *
3601 * Most of these calls are simple inline accessors so this doesn't
3602 * amount to much code.
3603 */
3604
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003605 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003606 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3607 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003608 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003609 goto Done;
3610 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003611
3612 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3613 pItem->val.string.ptr);
3614 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3615 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3616 /* This should never happen because pItem->val.string.ptr should
3617 * always be valid since it was just returned.
3618 */
3619 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3620 goto Done;
3621 }
3622
3623 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3624
3625 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003626 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003627
Laurence Lundblade02625d42020-06-25 14:41:41 -07003628 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003629 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003630 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003631Done:
3632 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003633}
3634
3635
Laurence Lundblade02625d42020-06-25 14:41:41 -07003636/*
3637 Public function, see header qcbor/qcbor_decode.h file
3638 */
3639void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003640 uint8_t uTagRequirement,
3641 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003642{
3643 if(pMe->uLastError != QCBOR_SUCCESS) {
3644 // Already in error state; do nothing.
3645 return;
3646 }
3647
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003648 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003649 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003650 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3651 if(pMe->uLastError != QCBOR_SUCCESS) {
3652 return;
3653 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003654
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003655 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003656 &Item,
3657 uTagRequirement,
3658 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003659}
3660
3661
Laurence Lundblade02625d42020-06-25 14:41:41 -07003662/*
3663 Public function, see header qcbor/qcbor_decode.h file
3664 */
3665void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003666 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003667 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003668 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003669{
3670 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003671 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003672
Laurence Lundblade93d89472020-10-03 22:30:50 -07003673 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3674 &Item,
3675 uTagRequirement,
3676 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003677}
3678
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003679
Laurence Lundblade02625d42020-06-25 14:41:41 -07003680/*
3681 Public function, see header qcbor/qcbor_decode.h file
3682 */
3683void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003684 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003685 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003686 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003687{
3688 QCBORItem Item;
3689 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3690
Laurence Lundblade93d89472020-10-03 22:30:50 -07003691 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3692 &Item,
3693 uTagRequirement,
3694 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003695}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003696
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003697
Laurence Lundblade02625d42020-06-25 14:41:41 -07003698/*
3699 Public function, see header qcbor/qcbor_decode.h file
3700 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003701void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003702{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003703 if(pMe->uLastError != QCBOR_SUCCESS) {
3704 // Already in error state; do nothing.
3705 return;
3706 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003707
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003708 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003709 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003710 return;
3711 }
3712
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003713 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3714
Laurence Lundblade02625d42020-06-25 14:41:41 -07003715 /*
3716 Reset the length of the UsefulInputBuf to what it was before
3717 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003718 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003719 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003720 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003721
3722
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003723 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003724 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003725}
3726
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003727
Laurence Lundbladee6430642020-03-14 21:15:44 -07003728
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003729
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003730static inline void
3731ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003732{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003733 if(pMe->uLastError != QCBOR_SUCCESS) {
3734 /* Already in error state, do nothing */
3735 return;
3736 }
3737
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003738 switch(pItem->uDataType) {
3739 case QCBOR_TYPE_TRUE:
3740 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003741 break;
3742
3743 case QCBOR_TYPE_FALSE:
3744 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003745 break;
3746
3747 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003748 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003749 break;
3750 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003751 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003752}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003753
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003754
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003755/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003756 * Public function, see header qcbor/qcbor_decode.h file
3757 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003759{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003760 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003761 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003762 return;
3763 }
3764
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765 QCBORItem Item;
3766
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003767 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3768
3769 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003770}
3771
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003772
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003773/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003774 * Public function, see header qcbor/qcbor_decode.h file
3775 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003776void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777{
3778 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003779 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003780
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003781 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003782}
3783
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003784
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003785/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003786 * Public function, see header qcbor/qcbor_decode.h file
3787 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003788void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3789{
3790 QCBORItem Item;
3791 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3792
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003793 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003794}
3795
3796
3797
Laurence Lundbladec7114722020-08-13 05:11:40 -07003798
3799static void ProcessEpochDate(QCBORDecodeContext *pMe,
3800 QCBORItem *pItem,
3801 uint8_t uTagRequirement,
3802 int64_t *pnTime)
3803{
3804 if(pMe->uLastError != QCBOR_SUCCESS) {
3805 // Already in error state, do nothing
3806 return;
3807 }
3808
3809 QCBORError uErr;
3810
3811 const TagSpecification TagSpec =
3812 {
3813 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003814 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3815 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003816 };
3817
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003818 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003819 if(uErr != QCBOR_SUCCESS) {
3820 goto Done;
3821 }
3822
3823 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3824 uErr = DecodeDateEpoch(pItem);
3825 if(uErr != QCBOR_SUCCESS) {
3826 goto Done;
3827 }
3828 }
3829
Laurence Lundblade9b334962020-08-27 10:55:53 -07003830 // Save the tags in the last item's tags in the decode context
3831 // for QCBORDecode_GetNthTagOfLast()
3832 CopyTags(pMe, pItem);
3833
Laurence Lundbladec7114722020-08-13 05:11:40 -07003834 *pnTime = pItem->val.epochDate.nSeconds;
3835
3836Done:
3837 pMe->uLastError = (uint8_t)uErr;
3838}
3839
3840
3841void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003842 uint8_t uTagRequirement,
3843 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003844{
3845 if(pMe->uLastError != QCBOR_SUCCESS) {
3846 // Already in error state, do nothing
3847 return;
3848 }
3849
3850 QCBORItem Item;
3851 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3852
3853 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3854}
3855
3856
3857void
3858QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3859 int64_t nLabel,
3860 uint8_t uTagRequirement,
3861 int64_t *pnTime)
3862{
3863 QCBORItem Item;
3864 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3865 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3866}
3867
3868
3869void
3870QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3871 const char *szLabel,
3872 uint8_t uTagRequirement,
3873 int64_t *pnTime)
3874{
3875 QCBORItem Item;
3876 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3877 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3878}
3879
3880
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003881
3882/*
Laurence Lundbladef21c4212021-05-13 03:11:09 -07003883 * Common processing for the RFC 8943 day-count tag. Mostly
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003884 * make sure the tag content is correct and copy forward any
3885 * further other tag numbers.
3886 */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003887static void ProcessEpochDays(QCBORDecodeContext *pMe,
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003888 QCBORItem *pItem,
3889 uint8_t uTagRequirement,
3890 int64_t *pnDays)
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003891{
3892 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003893 /* Already in error state, do nothing */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003894 return;
3895 }
3896
3897 QCBORError uErr;
3898
3899 const TagSpecification TagSpec =
3900 {
3901 uTagRequirement,
3902 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3903 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3904 };
3905
3906 uErr = CheckTagRequirement(TagSpec, pItem);
3907 if(uErr != QCBOR_SUCCESS) {
3908 goto Done;
3909 }
3910
Laurence Lundbladeac425ab2021-05-08 17:17:33 -07003911 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003912 uErr = DecodeDaysEpoch(pItem);
3913 if(uErr != QCBOR_SUCCESS) {
3914 goto Done;
3915 }
3916 }
3917
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003918 /* Save the tags in the last item's tags in the decode context
3919 * for QCBORDecode_GetNthTagOfLast()
3920 */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003921 CopyTags(pMe, pItem);
3922
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003923 *pnDays = pItem->val.epochDays;
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003924
3925Done:
3926 pMe->uLastError = (uint8_t)uErr;
3927}
3928
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003929
3930/*
3931 * Public function, see header qcbor/qcbor_decode.h
3932 */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003933void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
3934 uint8_t uTagRequirement,
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003935 int64_t *pnDays)
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003936{
3937 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003938 /* Already in error state, do nothing */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003939 return;
3940 }
3941
3942 QCBORItem Item;
3943 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3944
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003945 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003946}
3947
3948
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003949/*
3950 * Public function, see header qcbor/qcbor_decode.h
3951 */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003952void
3953QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
3954 int64_t nLabel,
3955 uint8_t uTagRequirement,
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003956 int64_t *pnDays)
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003957{
3958 QCBORItem Item;
3959 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003960 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003961}
3962
3963
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003964/*
3965 * Public function, see header qcbor/qcbor_decode.h
3966 */
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003967void
3968QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
3969 const char *szLabel,
3970 uint8_t uTagRequirement,
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003971 int64_t *pnDays)
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003972{
3973 QCBORItem Item;
3974 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade7d0f5732021-05-12 00:06:06 -07003975 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade58541fe2021-05-07 01:24:49 -07003976}
3977
3978
Laurence Lundbladec7114722020-08-13 05:11:40 -07003979
3980
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003981void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3982 TagSpecification TagSpec,
3983 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003984{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003985 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003986 // Already in error state, do nothing
3987 return;
3988 }
3989
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003990 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003991 QCBORItem Item;
3992
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003993 uError = QCBORDecode_GetNext(pMe, &Item);
3994 if(uError != QCBOR_SUCCESS) {
3995 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003996 return;
3997 }
3998
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003999 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004000
4001 if(pMe->uLastError == QCBOR_SUCCESS) {
4002 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004003 } else {
4004 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004005 }
4006}
4007
Laurence Lundbladec4537442020-04-14 18:53:22 -07004008
4009
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004010
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004011static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004012 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004013 UsefulBufC *pValue,
4014 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004015{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004016 const TagSpecification TagSpec =
4017 {
4018 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004019 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4020 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004021 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004022
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004023 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004024 if(uErr != QCBOR_SUCCESS) {
4025 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004026 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004027
4028 *pValue = pItem->val.string;
4029
4030 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4031 *pbIsNegative = false;
4032 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4033 *pbIsNegative = true;
4034 }
4035
4036 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004037}
4038
4039
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004040/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004041 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004042 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004043void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4044 uint8_t uTagRequirement,
4045 UsefulBufC *pValue,
4046 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004047{
4048 if(pMe->uLastError != QCBOR_SUCCESS) {
4049 // Already in error state, do nothing
4050 return;
4051 }
4052
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004053 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004054 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4055 if(uError != QCBOR_SUCCESS) {
4056 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004057 return;
4058 }
4059
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004060 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004061}
4062
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004063
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004064/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004065 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004066*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004067void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4068 int64_t nLabel,
4069 uint8_t uTagRequirement,
4070 UsefulBufC *pValue,
4071 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004072{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004073 QCBORItem Item;
4074 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004075 if(pMe->uLastError != QCBOR_SUCCESS) {
4076 return;
4077 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004078
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004079 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004080}
4081
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004082
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004083/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004084 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004085*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004086void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4087 const char *szLabel,
4088 uint8_t uTagRequirement,
4089 UsefulBufC *pValue,
4090 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004091{
4092 QCBORItem Item;
4093 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004094 if(pMe->uLastError != QCBOR_SUCCESS) {
4095 return;
4096 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004097
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004098 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004099}
4100
4101
4102
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004103
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004104// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004105QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
4106 const QCBORItem *pItem,
4107 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07004108 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004109{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004110 const TagSpecification TagSpecText =
4111 {
4112 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004113 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4114 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004115 };
4116 const TagSpecification TagSpecBinary =
4117 {
4118 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004119 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4120 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004121 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004122
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004123 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004124
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004125 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004126 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004127 if(pbIsTag257 != NULL) {
4128 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004129 }
4130 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004131 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004132 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004133 if(pbIsTag257 != NULL) {
4134 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004135 }
4136 uReturn = QCBOR_SUCCESS;
4137
4138 } else {
4139 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4140 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004141
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004142 return uReturn;
4143}
4144
Laurence Lundblade93d89472020-10-03 22:30:50 -07004145// Improvement: add methods for wrapped CBOR, a simple alternate
4146// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004147
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004148
4149
4150
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004151#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004152
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004153typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004154
4155
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004156// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004157static QCBORError
4158Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004159{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004160 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004161
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004162 if(uResult != 0) {
4163 /* This loop will run a maximum of 19 times because
4164 * UINT64_MAX < 10 ^^ 19. More than that will cause
4165 * exit with the overflow error
4166 */
4167 for(; nExponent > 0; nExponent--) {
4168 if(uResult > UINT64_MAX / 10) {
4169 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4170 }
4171 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004172 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004173
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004174 for(; nExponent < 0; nExponent++) {
4175 uResult = uResult / 10;
4176 if(uResult == 0) {
4177 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4178 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004179 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004180 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004181 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004182
4183 *puResult = uResult;
4184
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004185 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004186}
4187
4188
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004189// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004190static QCBORError
4191Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004192{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004193 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004194
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004195 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004196
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004197 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004198 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004199 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004200 */
4201 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004202 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004203 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004204 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004205 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004206 nExponent--;
4207 }
4208
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004209 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004210 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004211 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4212 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004213 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004214 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004215 }
4216
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004217 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004218
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004219 return QCBOR_SUCCESS;
4220}
4221
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004222
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004223/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004224 Compute value with signed mantissa and signed result. Works with
4225 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004226 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004227static inline QCBORError ExponentiateNN(int64_t nMantissa,
4228 int64_t nExponent,
4229 int64_t *pnResult,
4230 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004231{
4232 uint64_t uResult;
4233
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004234 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004235 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004236 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4237
4238 // Do the exponentiation of the positive mantissa
4239 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4240 if(uReturn) {
4241 return uReturn;
4242 }
4243
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004244
Laurence Lundblade983500d2020-05-14 11:49:34 -07004245 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4246 of INT64_MIN. This assumes two's compliment representation where
4247 INT64_MIN is one increment farther from 0 than INT64_MAX.
4248 Trying to write -INT64_MIN doesn't work to get this because the
4249 compiler tries to work with an int64_t which can't represent
4250 -INT64_MIN.
4251 */
4252 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4253
4254 // Error out if too large
4255 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004256 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4257 }
4258
4259 // Casts are safe because of checks above
4260 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4261
4262 return QCBOR_SUCCESS;
4263}
4264
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004265
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004266/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004267 Compute value with signed mantissa and unsigned result. Works with
4268 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004269 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004270static inline QCBORError ExponentitateNU(int64_t nMantissa,
4271 int64_t nExponent,
4272 uint64_t *puResult,
4273 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004274{
4275 if(nMantissa < 0) {
4276 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4277 }
4278
4279 // Cast to unsigned is OK because of check for negative
4280 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4281 // Exponentiation is straight forward
4282 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4283}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004284
4285
4286/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004287 Compute value with signed mantissa and unsigned result. Works with
4288 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004289 */
4290static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4291 int64_t nExponent,
4292 uint64_t *puResult,
4293 fExponentiator pfExp)
4294{
4295 return (*pfExp)(uMantissa, nExponent, puResult);
4296}
4297
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004298#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004299
4300
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004301
4302
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004303
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004304static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004305{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004306 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004307
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004308 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004309 const uint8_t *pByte = BigNum.ptr;
4310 size_t uLen = BigNum.len;
4311 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004312 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004313 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004314 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004315 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004316 }
4317
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004318 *pResult = uResult;
4319 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004320}
4321
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322
Laurence Lundblade887add82020-05-17 05:50:34 -07004323static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004324{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004325 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004326}
4327
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004328
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004329static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004330{
4331 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004332 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4333 if(uError) {
4334 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004335 }
4336 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4337 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004338 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004339}
4340
4341
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004342static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004343{
4344 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004345 /* The negative integer furthest from zero for a C int64_t is
4346 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4347 negative number in CBOR is computed as -n - 1 where n is the
4348 encoded integer, where n is what is in the variable BigNum. When
4349 converting BigNum to a uint64_t, the maximum value is thus
4350 INT64_MAX, so that when it -n - 1 is applied to it the result will
4351 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004352
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004353 -n - 1 <= INT64_MIN.
4354 -n - 1 <= -INT64_MAX - 1
4355 n <= INT64_MAX.
4356 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004357 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004358 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004359 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004360 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004361
4362 /// Now apply -n - 1. The cast is safe because
4363 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4364 // is the largest positive integer that an int64_t can
4365 // represent. */
4366 *pnResult = -(int64_t)uResult - 1;
4367
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004368 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004369}
4370
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004371
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004372
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004373
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004374
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004375/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004376Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004377
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004378\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004379
Laurence Lundblade93d89472020-10-03 22:30:50 -07004380\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4381 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004382
4383\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4384
Laurence Lundblade93d89472020-10-03 22:30:50 -07004385\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4386 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004388static QCBORError
4389ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004390{
4391 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004392 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004393 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004394#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004395 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004396 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4397 http://www.cplusplus.com/reference/cmath/llround/
4398 */
4399 // Not interested in FE_INEXACT
4400 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004401 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4402 *pnValue = llround(pItem->val.dfnum);
4403 } else {
4404 *pnValue = lroundf(pItem->val.fnum);
4405 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004406 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4407 // llround() shouldn't result in divide by zero, but catch
4408 // it here in case it unexpectedly does. Don't try to
4409 // distinguish between the various exceptions because it seems
4410 // they vary by CPU, compiler and OS.
4411 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004412 }
4413 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004414 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004415 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004416#else
4417 return QCBOR_ERR_HW_FLOAT_DISABLED;
4418#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004419 break;
4420
4421 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004422 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004423 *pnValue = pItem->val.int64;
4424 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004426 }
4427 break;
4428
4429 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004430 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004431 if(pItem->val.uint64 < INT64_MAX) {
4432 *pnValue = pItem->val.int64;
4433 } else {
4434 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4435 }
4436 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004437 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004438 }
4439 break;
4440
4441 default:
4442 return QCBOR_ERR_UNEXPECTED_TYPE;
4443 }
4444 return QCBOR_SUCCESS;
4445}
4446
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004447
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004448void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004449 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004450 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004451 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004452{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004453 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004454 return;
4455 }
4456
Laurence Lundbladee6430642020-03-14 21:15:44 -07004457 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004458 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4459 if(uError) {
4460 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004461 return;
4462 }
4463
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004464 if(pItem) {
4465 *pItem = Item;
4466 }
4467
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004468 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004469}
4470
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004472void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4473 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004475 int64_t *pnValue,
4476 QCBORItem *pItem)
4477{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004478 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004479 if(pMe->uLastError != QCBOR_SUCCESS) {
4480 return;
4481 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004482
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004484}
4485
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004486
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004487void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4488 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004489 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004490 int64_t *pnValue,
4491 QCBORItem *pItem)
4492{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004493 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004494 if(pMe->uLastError != QCBOR_SUCCESS) {
4495 return;
4496 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004497
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004499}
4500
4501
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004502/*
4503 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004504
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506
Laurence Lundblade93d89472020-10-03 22:30:50 -07004507 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4508 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509
4510 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4511
Laurence Lundblade93d89472020-10-03 22:30:50 -07004512 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4513 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004514 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004515static QCBORError
4516Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004517{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004518 switch(pItem->uDataType) {
4519
4520 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004521 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004522 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004523 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004524 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004525 }
4526 break;
4527
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004528 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004529 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004530 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004531 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004532 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004533 }
4534 break;
4535
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004536#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004537 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004538 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004539 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004540 pItem->val.expAndMantissa.nExponent,
4541 pnValue,
4542 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004543 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004544 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004545 }
4546 break;
4547
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004548 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004550 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004551 pItem->val.expAndMantissa.nExponent,
4552 pnValue,
4553 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004554 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004556 }
4557 break;
4558
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004559 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004560 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004561 int64_t nMantissa;
4562 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004563 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4564 if(uErr) {
4565 return uErr;
4566 }
4567 return ExponentiateNN(nMantissa,
4568 pItem->val.expAndMantissa.nExponent,
4569 pnValue,
4570 Exponentitate10);
4571 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004572 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004573 }
4574 break;
4575
4576 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004577 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004578 int64_t nMantissa;
4579 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004580 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4581 if(uErr) {
4582 return uErr;
4583 }
4584 return ExponentiateNN(nMantissa,
4585 pItem->val.expAndMantissa.nExponent,
4586 pnValue,
4587 Exponentitate10);
4588 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004589 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004590 }
4591 break;
4592
4593 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004594 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004595 int64_t nMantissa;
4596 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004597 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4598 if(uErr) {
4599 return uErr;
4600 }
4601 return ExponentiateNN(nMantissa,
4602 pItem->val.expAndMantissa.nExponent,
4603 pnValue,
4604 Exponentitate2);
4605 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004606 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004607 }
4608 break;
4609
4610 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004611 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004612 int64_t nMantissa;
4613 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004614 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4615 if(uErr) {
4616 return uErr;
4617 }
4618 return ExponentiateNN(nMantissa,
4619 pItem->val.expAndMantissa.nExponent,
4620 pnValue,
4621 Exponentitate2);
4622 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004623 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004624 }
4625 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004626#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004627
Laurence Lundbladee6430642020-03-14 21:15:44 -07004628
Laurence Lundbladec4537442020-04-14 18:53:22 -07004629 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004630 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004631}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004632
4633
Laurence Lundbladec4537442020-04-14 18:53:22 -07004634/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004635 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004636 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004637void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004638{
4639 QCBORItem Item;
4640
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004641 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004642
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004643 if(pMe->uLastError == QCBOR_SUCCESS) {
4644 // The above conversion succeeded
4645 return;
4646 }
4647
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004648 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004649 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004650 return;
4651 }
4652
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004653 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004654}
4655
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656
4657/*
4658Public function, see header qcbor/qcbor_decode.h file
4659*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004660void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4661 int64_t nLabel,
4662 uint32_t uConvertTypes,
4663 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004664{
4665 QCBORItem Item;
4666
Laurence Lundblade93d89472020-10-03 22:30:50 -07004667 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4668 nLabel,
4669 uConvertTypes,
4670 pnValue,
4671 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004672
4673 if(pMe->uLastError == QCBOR_SUCCESS) {
4674 // The above conversion succeeded
4675 return;
4676 }
4677
4678 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4679 // The above conversion failed in a way that code below can't correct
4680 return;
4681 }
4682
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004683 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004684}
4685
4686
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004687/*
4688Public function, see header qcbor/qcbor_decode.h file
4689*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004690void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4691 const char *szLabel,
4692 uint32_t uConvertTypes,
4693 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004694{
4695 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004696 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4697 szLabel,
4698 uConvertTypes,
4699 pnValue,
4700 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004701
4702 if(pMe->uLastError == QCBOR_SUCCESS) {
4703 // The above conversion succeeded
4704 return;
4705 }
4706
4707 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4708 // The above conversion failed in a way that code below can't correct
4709 return;
4710 }
4711
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004712 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004713}
4714
4715
Laurence Lundblade93d89472020-10-03 22:30:50 -07004716static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717{
4718 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004719 case QCBOR_TYPE_DOUBLE:
4720 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004721#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004722 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004723 // Can't use llround here because it will not convert values
4724 // greater than INT64_MAX and less than UINT64_MAX that
4725 // need to be converted so it is more complicated.
4726 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4727 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4728 if(isnan(pItem->val.dfnum)) {
4729 return QCBOR_ERR_FLOAT_EXCEPTION;
4730 } else if(pItem->val.dfnum < 0) {
4731 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4732 } else {
4733 double dRounded = round(pItem->val.dfnum);
4734 // See discussion in DecodeDateEpoch() for
4735 // explanation of - 0x7ff
4736 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4737 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4738 }
4739 *puValue = (uint64_t)dRounded;
4740 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004741 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004742 if(isnan(pItem->val.fnum)) {
4743 return QCBOR_ERR_FLOAT_EXCEPTION;
4744 } else if(pItem->val.fnum < 0) {
4745 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4746 } else {
4747 float fRounded = roundf(pItem->val.fnum);
4748 // See discussion in DecodeDateEpoch() for
4749 // explanation of - 0x7ff
4750 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4751 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4752 }
4753 *puValue = (uint64_t)fRounded;
4754 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004755 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004756 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4757 // round() and roundf() shouldn't result in exceptions here, but
4758 // catch them to be robust and thorough. Don't try to
4759 // distinguish between the various exceptions because it seems
4760 // they vary by CPU, compiler and OS.
4761 return QCBOR_ERR_FLOAT_EXCEPTION;
4762 }
4763
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004764 } else {
4765 return QCBOR_ERR_UNEXPECTED_TYPE;
4766 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004767#else
4768 return QCBOR_ERR_HW_FLOAT_DISABLED;
4769#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004770 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004771
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004772 case QCBOR_TYPE_INT64:
4773 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4774 if(pItem->val.int64 >= 0) {
4775 *puValue = (uint64_t)pItem->val.int64;
4776 } else {
4777 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4778 }
4779 } else {
4780 return QCBOR_ERR_UNEXPECTED_TYPE;
4781 }
4782 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004784 case QCBOR_TYPE_UINT64:
4785 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4786 *puValue = pItem->val.uint64;
4787 } else {
4788 return QCBOR_ERR_UNEXPECTED_TYPE;
4789 }
4790 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004791
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004792 default:
4793 return QCBOR_ERR_UNEXPECTED_TYPE;
4794 }
4795
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004796 return QCBOR_SUCCESS;
4797}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004798
4799
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004800void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004801 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004803 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004804{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004805 if(pMe->uLastError != QCBOR_SUCCESS) {
4806 return;
4807 }
4808
Laurence Lundbladec4537442020-04-14 18:53:22 -07004809 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004810
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004811 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4812 if(uError) {
4813 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004814 return;
4815 }
4816
Laurence Lundbladea826c502020-05-10 21:07:00 -07004817 if(pItem) {
4818 *pItem = Item;
4819 }
4820
Laurence Lundblade93d89472020-10-03 22:30:50 -07004821 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004822}
4823
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004824
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004825void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004827 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004828 uint64_t *puValue,
4829 QCBORItem *pItem)
4830{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004831 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004832 if(pMe->uLastError != QCBOR_SUCCESS) {
4833 return;
4834 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004835
Laurence Lundblade93d89472020-10-03 22:30:50 -07004836 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837}
4838
4839
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004840void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004842 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004843 uint64_t *puValue,
4844 QCBORItem *pItem)
4845{
4846 if(pMe->uLastError != QCBOR_SUCCESS) {
4847 return;
4848 }
4849
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004850 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004851 if(pMe->uLastError != QCBOR_SUCCESS) {
4852 return;
4853 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854
Laurence Lundblade93d89472020-10-03 22:30:50 -07004855 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856}
4857
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004858
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004859
Laurence Lundblade93d89472020-10-03 22:30:50 -07004860static QCBORError
4861UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 switch(pItem->uDataType) {
4864
4865 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4868 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004869 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870 }
4871 break;
4872
4873 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004874 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004875 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4876 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004877 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004878 }
4879 break;
4880
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004881#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882
4883 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004884 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004886 pItem->val.expAndMantissa.nExponent,
4887 puValue,
4888 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004890 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891 }
4892 break;
4893
4894 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004895 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004896 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4897 pItem->val.expAndMantissa.nExponent,
4898 puValue,
4899 Exponentitate2);
4900 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902 }
4903 break;
4904
4905 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004906 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004907 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004908 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004909 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004910 if(uErr != QCBOR_SUCCESS) {
4911 return uErr;
4912 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004913 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914 pItem->val.expAndMantissa.nExponent,
4915 puValue,
4916 Exponentitate10);
4917 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004918 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004919 }
4920 break;
4921
4922 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004923 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004924 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
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_BIGFLOAT_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 Exponentitate2);
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_BIGFLOAT_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;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004954#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004955 default:
4956 return QCBOR_ERR_UNEXPECTED_TYPE;
4957 }
4958}
4959
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004960
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004961/*
4962 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004963 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004964void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004965{
4966 QCBORItem Item;
4967
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004968 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004969
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004970 if(pMe->uLastError == QCBOR_SUCCESS) {
4971 // The above conversion succeeded
4972 return;
4973 }
4974
4975 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4976 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004977 return;
4978 }
4979
Laurence Lundblade93d89472020-10-03 22:30:50 -07004980 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004981}
4982
Laurence Lundbladec4537442020-04-14 18:53:22 -07004983
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004984/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004985 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004987void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004988 int64_t nLabel,
4989 uint32_t uConvertTypes,
4990 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004991{
4992 QCBORItem Item;
4993
Laurence Lundblade93d89472020-10-03 22:30:50 -07004994 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4995 nLabel,
4996 uConvertTypes,
4997 puValue,
4998 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004999
5000 if(pMe->uLastError == QCBOR_SUCCESS) {
5001 // The above conversion succeeded
5002 return;
5003 }
5004
5005 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5006 // The above conversion failed in a way that code below can't correct
5007 return;
5008 }
5009
Laurence Lundblade93d89472020-10-03 22:30:50 -07005010 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005011}
5012
5013
5014/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005015 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005017void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005018 const char *szLabel,
5019 uint32_t uConvertTypes,
5020 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005021{
5022 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005023 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5024 szLabel,
5025 uConvertTypes,
5026 puValue,
5027 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005028
5029 if(pMe->uLastError == QCBOR_SUCCESS) {
5030 // The above conversion succeeded
5031 return;
5032 }
5033
5034 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5035 // The above conversion failed in a way that code below can't correct
5036 return;
5037 }
5038
Laurence Lundblade93d89472020-10-03 22:30:50 -07005039 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005040}
5041
5042
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005043
5044
Laurence Lundblade9b334962020-08-27 10:55:53 -07005045static QCBORError ConvertDouble(const QCBORItem *pItem,
5046 uint32_t uConvertTypes,
5047 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005048{
5049 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005050 case QCBOR_TYPE_FLOAT:
5051#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5052 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5053 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005054 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005055 *pdValue = (double)pItem->val.fnum;
5056 } else {
5057 return QCBOR_ERR_UNEXPECTED_TYPE;
5058 }
5059 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005060#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005061 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005062#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005063 break;
5064
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005065 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005066 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5067 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005068 *pdValue = pItem->val.dfnum;
5069 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005070 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005071 }
5072 }
5073 break;
5074
5075 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005076#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005077 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005078 // A simple cast seems to do the job with no worry of exceptions.
5079 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005080 *pdValue = (double)pItem->val.int64;
5081
5082 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005083 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005084 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005085#else
5086 return QCBOR_ERR_HW_FLOAT_DISABLED;
5087#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005088 break;
5089
5090 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005091#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005092 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005093 // A simple cast seems to do the job with no worry of exceptions.
5094 // There will be precision loss for some values.
5095 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005096 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005097 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005098 }
5099 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005100#else
5101 return QCBOR_ERR_HW_FLOAT_DISABLED;
5102#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005103
5104 default:
5105 return QCBOR_ERR_UNEXPECTED_TYPE;
5106 }
5107
5108 return QCBOR_SUCCESS;
5109}
5110
5111
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005112void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005113 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005114 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005115 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005116{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005117 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005118 return;
5119 }
5120
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005121 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005122
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005123 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005124 if(uError) {
5125 pMe->uLastError = (uint8_t)uError;
5126 return;
5127 }
5128
5129 if(pItem) {
5130 *pItem = Item;
5131 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005132
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005133 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005134}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005135
Laurence Lundbladec4537442020-04-14 18:53:22 -07005136
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005137void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5138 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005139 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005140 double *pdValue,
5141 QCBORItem *pItem)
5142{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005143 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005144 if(pMe->uLastError != QCBOR_SUCCESS) {
5145 return;
5146 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005147
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005148 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005149}
5150
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005151
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005152void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5153 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005154 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005155 double *pdValue,
5156 QCBORItem *pItem)
5157{
5158 if(pMe->uLastError != QCBOR_SUCCESS) {
5159 return;
5160 }
5161
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005162 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005163 if(pMe->uLastError != QCBOR_SUCCESS) {
5164 return;
5165 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005166
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005167 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005168}
5169
5170
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005171#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005172static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5173{
5174 double dResult;
5175
5176 dResult = 0.0;
5177 const uint8_t *pByte = BigNum.ptr;
5178 size_t uLen = BigNum.len;
5179 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005180 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005181 while(uLen--) {
5182 dResult = (dResult * 256.0) + (double)*pByte++;
5183 }
5184
5185 return dResult;
5186}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005187#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5188
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005189
Laurence Lundblade93d89472020-10-03 22:30:50 -07005190static QCBORError
5191DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005192{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005193#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005194 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005195 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5196
5197 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005198 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005199
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005200#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005201 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005202 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005203 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005204 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5205 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5206 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005207 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005208 }
5209 break;
5210
5211 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005212 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005213 // Underflow gives 0, overflow gives infinity
5214 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5215 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005216 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005217 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005218 }
5219 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005220#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005221
5222 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005223 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005224 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5225 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005226 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005227 }
5228 break;
5229
5230 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005231 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005232 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005233 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005234 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005235 }
5236 break;
5237
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005238#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005239 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005240 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005241 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5242 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5243 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005244 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005245 }
5246 break;
5247
5248 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005249 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005250 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5251 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5252 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005253 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005254 }
5255 break;
5256
5257 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005258 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005259 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5260 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5261 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005262 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005263 }
5264 break;
5265
5266 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005267 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005268 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005269 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5270 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005271 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005272 }
5273 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005274#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005275
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005276 default:
5277 return QCBOR_ERR_UNEXPECTED_TYPE;
5278 }
5279
5280 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005281
5282#else
5283 (void)pItem;
5284 (void)uConvertTypes;
5285 (void)pdValue;
5286 return QCBOR_ERR_HW_FLOAT_DISABLED;
5287#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5288
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005289}
5290
5291
5292/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005293 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005294*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005295void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5296 uint32_t uConvertTypes,
5297 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005298{
5299
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005300 QCBORItem Item;
5301
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005302 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005303
5304 if(pMe->uLastError == QCBOR_SUCCESS) {
5305 // The above conversion succeeded
5306 return;
5307 }
5308
5309 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5310 // The above conversion failed in a way that code below can't correct
5311 return;
5312 }
5313
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005314 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005315}
5316
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005317
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_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5322 int64_t nLabel,
5323 uint32_t uConvertTypes,
5324 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005325{
5326 QCBORItem Item;
5327
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005328 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -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 Lundblade7e5be1d2020-05-24 21:17:28 -07005341}
5342
5343
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_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5348 const char *szLabel,
5349 uint32_t uConvertTypes,
5350 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005351{
5352 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005353 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005354
5355 if(pMe->uLastError == QCBOR_SUCCESS) {
5356 // The above conversion succeeded
5357 return;
5358 }
5359
5360 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5361 // The above conversion failed in a way that code below can't correct
5362 return;
5363 }
5364
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005365 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005366}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005367
5368
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005369
5370
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005371#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005372static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5373{
5374 while((uInt & 0xff00000000000000UL) == 0) {
5375 uInt = uInt << 8;
5376 };
5377
5378 UsefulOutBuf UOB;
5379
5380 UsefulOutBuf_Init(&UOB, Buffer);
5381
5382 while(uInt) {
5383 const uint64_t xx = uInt & 0xff00000000000000UL;
5384 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5385 uInt = uInt << 8;
5386 (void)xx;
5387 }
5388
5389 return UsefulOutBuf_OutUBuf(&UOB);
5390}
5391
5392
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005393static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5394 TagSpecification TagSpec,
5395 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005396{
5397 QCBORError uErr;
5398 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005399 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005400 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005401 if(uErr != QCBOR_SUCCESS) {
5402 goto Done;
5403 }
5404
5405 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5406 break; // Successful exit. Moving on to finish decoding.
5407 }
5408
5409 // The item is an array, which means an undecoded
5410 // mantissa and exponent, so decode it. It will then
5411 // have a different type and exit the loop if.
5412 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5413 if(uErr != QCBOR_SUCCESS) {
5414 goto Done;
5415 }
5416
5417 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005418 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005419 }
5420Done:
5421 return uErr;
5422}
5423
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005424
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005425static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 TagSpecification TagSpec,
5427 QCBORItem *pItem,
5428 int64_t *pnMantissa,
5429 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005430{
5431 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005432
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005433 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005434 if(uErr != QCBOR_SUCCESS) {
5435 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005436 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005437
Laurence Lundblade9b334962020-08-27 10:55:53 -07005438 switch (pItem->uDataType) {
5439
5440 case QCBOR_TYPE_DECIMAL_FRACTION:
5441 case QCBOR_TYPE_BIGFLOAT:
5442 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5443 *pnExponent = pItem->val.expAndMantissa.nExponent;
5444 break;
5445
5446 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5447 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5448 *pnExponent = pItem->val.expAndMantissa.nExponent;
5449 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5450 break;
5451
5452 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5453 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5454 *pnExponent = pItem->val.expAndMantissa.nExponent;
5455 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5456 break;
5457
5458 default:
5459 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5460 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005461
5462 Done:
5463 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005464}
5465
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005466
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005467static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005468 TagSpecification TagSpec,
5469 QCBORItem *pItem,
5470 UsefulBuf BufferForMantissa,
5471 UsefulBufC *pMantissa,
5472 bool *pbIsNegative,
5473 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005474{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005475 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005476
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005478 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005479 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005480 }
5481
5482 uint64_t uMantissa;
5483
5484 switch (pItem->uDataType) {
5485
5486 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005487 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005488 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5489 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5490 *pbIsNegative = false;
5491 } else {
5492 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5493 *pbIsNegative = true;
5494 }
5495 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5496 *pnExponent = pItem->val.expAndMantissa.nExponent;
5497 break;
5498
5499 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005500 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005501 *pnExponent = pItem->val.expAndMantissa.nExponent;
5502 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5503 *pbIsNegative = false;
5504 break;
5505
5506 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005507 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005508 *pnExponent = pItem->val.expAndMantissa.nExponent;
5509 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5510 *pbIsNegative = true;
5511 break;
5512
5513 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005514 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005515 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005516
5517Done:
5518 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005519}
5520
5521
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005522/*
5523 Public function, see header qcbor/qcbor_decode.h file
5524*/
5525void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5526 uint8_t uTagRequirement,
5527 int64_t *pnMantissa,
5528 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005529{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005530 if(pMe->uLastError != QCBOR_SUCCESS) {
5531 return;
5532 }
5533
5534 QCBORItem Item;
5535 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5536 if(uError) {
5537 pMe->uLastError = (uint8_t)uError;
5538 return;
5539 }
5540
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005541 const TagSpecification TagSpec =
5542 {
5543 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005544 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5545 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5546 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005547 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005548
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005549 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005550}
5551
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005552
5553/*
5554 Public function, see header qcbor/qcbor_decode.h file
5555*/
5556void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005557 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005558 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005559 int64_t *pnMantissa,
5560 int64_t *pnExponent)
5561{
5562 if(pMe->uLastError != QCBOR_SUCCESS) {
5563 return;
5564 }
5565
5566 QCBORItem Item;
5567 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5568
5569 const TagSpecification TagSpec =
5570 {
5571 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005572 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5573 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5574 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005575 };
5576
5577 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5578}
5579
5580
5581/*
5582 Public function, see header qcbor/qcbor_decode.h file
5583*/
5584void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005585 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005586 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005587 int64_t *pnMantissa,
5588 int64_t *pnExponent)
5589{
5590 if(pMe->uLastError != QCBOR_SUCCESS) {
5591 return;
5592 }
5593
5594 QCBORItem Item;
5595 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5596
5597 const TagSpecification TagSpec =
5598 {
5599 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005600 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5601 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5602 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005603 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005604
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005605 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5606}
5607
5608
5609/*
5610 Public function, see header qcbor/qcbor_decode.h file
5611*/
5612void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5613 uint8_t uTagRequirement,
5614 UsefulBuf MantissaBuffer,
5615 UsefulBufC *pMantissa,
5616 bool *pbMantissaIsNegative,
5617 int64_t *pnExponent)
5618{
5619 if(pMe->uLastError != QCBOR_SUCCESS) {
5620 return;
5621 }
5622
5623 QCBORItem Item;
5624 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5625 if(uError) {
5626 pMe->uLastError = (uint8_t)uError;
5627 return;
5628 }
5629
5630 const TagSpecification TagSpec =
5631 {
5632 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005633 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5634 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5635 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005636 };
5637
Laurence Lundblade93d89472020-10-03 22:30:50 -07005638 ProcessMantissaAndExponentBig(pMe,
5639 TagSpec,
5640 &Item,
5641 MantissaBuffer,
5642 pMantissa,
5643 pbMantissaIsNegative,
5644 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005645}
5646
5647
5648/*
5649 Public function, see header qcbor/qcbor_decode.h file
5650*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005651void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005652 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005653 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005654 UsefulBuf BufferForMantissa,
5655 UsefulBufC *pMantissa,
5656 bool *pbIsNegative,
5657 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005658{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005659 if(pMe->uLastError != QCBOR_SUCCESS) {
5660 return;
5661 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005662
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005663 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005664 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005665 if(pMe->uLastError != QCBOR_SUCCESS) {
5666 return;
5667 }
5668
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005669 const TagSpecification TagSpec =
5670 {
5671 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005672 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5673 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5674 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005675 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005676
Laurence Lundblade93d89472020-10-03 22:30:50 -07005677 ProcessMantissaAndExponentBig(pMe,
5678 TagSpec,
5679 &Item,
5680 BufferForMantissa,
5681 pMantissa,
5682 pbIsNegative,
5683 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005684}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005685
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005686
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005687/*
5688 Public function, see header qcbor/qcbor_decode.h file
5689*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005690void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005691 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005692 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005693 UsefulBuf BufferForMantissa,
5694 UsefulBufC *pMantissa,
5695 bool *pbIsNegative,
5696 int64_t *pnExponent)
5697{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005698 if(pMe->uLastError != QCBOR_SUCCESS) {
5699 return;
5700 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005701
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005702 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005703 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5704 if(pMe->uLastError != QCBOR_SUCCESS) {
5705 return;
5706 }
5707
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005708 const TagSpecification TagSpec =
5709 {
5710 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005711 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5712 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5713 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005714 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005715
5716 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5717}
5718
5719
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005720/*
5721 Public function, see header qcbor/qcbor_decode.h file
5722*/
5723void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5724 uint8_t uTagRequirement,
5725 int64_t *pnMantissa,
5726 int64_t *pnExponent)
5727{
5728 if(pMe->uLastError != QCBOR_SUCCESS) {
5729 return;
5730 }
5731
5732 QCBORItem Item;
5733 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5734 if(uError) {
5735 pMe->uLastError = (uint8_t)uError;
5736 return;
5737 }
5738 const TagSpecification TagSpec =
5739 {
5740 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005741 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5742 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5743 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005744 };
5745
5746 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5747}
5748
5749
5750/*
5751 Public function, see header qcbor/qcbor_decode.h file
5752*/
5753void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005754 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005755 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005756 int64_t *pnMantissa,
5757 int64_t *pnExponent)
5758{
5759 if(pMe->uLastError != QCBOR_SUCCESS) {
5760 return;
5761 }
5762
5763 QCBORItem Item;
5764 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5765 if(pMe->uLastError != QCBOR_SUCCESS) {
5766 return;
5767 }
5768
5769 const TagSpecification TagSpec =
5770 {
5771 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005772 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5773 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5774 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005775 };
5776
5777 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5778}
5779
5780
5781/*
5782 Public function, see header qcbor/qcbor_decode.h file
5783*/
5784void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005785 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005786 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005787 int64_t *pnMantissa,
5788 int64_t *pnExponent)
5789{
5790 if(pMe->uLastError != QCBOR_SUCCESS) {
5791 return;
5792 }
5793
5794 QCBORItem Item;
5795 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5796 if(pMe->uLastError != QCBOR_SUCCESS) {
5797 return;
5798 }
5799
5800 const TagSpecification TagSpec =
5801 {
5802 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005803 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5804 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5805 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005806 };
5807
5808 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5809}
5810
5811
5812/*
5813 Public function, see header qcbor/qcbor_decode.h file
5814*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005815void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5816 uint8_t uTagRequirement,
5817 UsefulBuf MantissaBuffer,
5818 UsefulBufC *pMantissa,
5819 bool *pbMantissaIsNegative,
5820 int64_t *pnExponent)
5821{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005822 if(pMe->uLastError != QCBOR_SUCCESS) {
5823 return;
5824 }
5825
5826 QCBORItem Item;
5827 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5828 if(uError) {
5829 pMe->uLastError = (uint8_t)uError;
5830 return;
5831 }
5832
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005833 const TagSpecification TagSpec =
5834 {
5835 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005836 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5837 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5838 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005839 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005840
5841 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005842}
5843
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005844
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005845/*
5846 Public function, see header qcbor/qcbor_decode.h file
5847*/
5848void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005849 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005850 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005851 UsefulBuf BufferForMantissa,
5852 UsefulBufC *pMantissa,
5853 bool *pbIsNegative,
5854 int64_t *pnExponent)
5855{
5856 if(pMe->uLastError != QCBOR_SUCCESS) {
5857 return;
5858 }
5859
5860 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005861 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5862 if(pMe->uLastError != QCBOR_SUCCESS) {
5863 return;
5864 }
5865
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005866 const TagSpecification TagSpec =
5867 {
5868 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005869 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5870 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5871 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005872 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005873
Laurence Lundblade93d89472020-10-03 22:30:50 -07005874 ProcessMantissaAndExponentBig(pMe,
5875 TagSpec,
5876 &Item,
5877 BufferForMantissa,
5878 pMantissa,
5879 pbIsNegative,
5880 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005881}
5882
5883
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005884/*
5885 Public function, see header qcbor/qcbor_decode.h file
5886*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005887void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005888 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005889 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005890 UsefulBuf BufferForMantissa,
5891 UsefulBufC *pMantissa,
5892 bool *pbIsNegative,
5893 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005894{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005895 if(pMe->uLastError != QCBOR_SUCCESS) {
5896 return;
5897 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005898
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005899 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005900 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5901 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005902 return;
5903 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005904
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005905 const TagSpecification TagSpec =
5906 {
5907 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005908 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5909 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5910 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005911 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005912
Laurence Lundblade93d89472020-10-03 22:30:50 -07005913 ProcessMantissaAndExponentBig(pMe,
5914 TagSpec,
5915 &Item,
5916 BufferForMantissa,
5917 pMantissa,
5918 pbIsNegative,
5919 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005920}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005921
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005922#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */