blob: 31cc2cbabf9c8dba722529c11d726b4a7a803ca5 [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 Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, 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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade53b945a2020-12-27 02:05:01 -080039
Laurence Lundblade6474c982020-12-26 22:14:34 -080040#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
Laurence Lundblade53b945a2020-12-27 02:05:01 -080044
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 Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade6474c982020-12-26 22:14:34 -080050 * This casts away the const-ness of a pointer, usually so it can be
51 * freed or realloced.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053052 */
53#define UNCONST_POINTER(ptr) ((void *)(ptr))
54
Laurence Lundbladea9489f82020-09-12 13:50:56 -070055#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
Laurence Lundblade6474c982020-12-26 22:14:34 -080058
59
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070060static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070061QCBORItem_IsMapOrArray(const QCBORItem *pMe)
62{
63 const uint8_t uDataType = pMe->uDataType;
64 return uDataType == QCBOR_TYPE_MAP ||
65 uDataType == QCBOR_TYPE_ARRAY ||
66 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
67}
68
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070069static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070070QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != 0) {
77 return false;
78 }
79 return true;
80}
81
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070082static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070083QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
84{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080085#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 if(!QCBORItem_IsMapOrArray(pMe)){
87 return false;
88 }
89
90 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
91 return false;
92 }
93 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080094#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
95 (void)pMe;
96 return false;
97#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070098}
99
100
Laurence Lundbladeee851742020-01-08 08:37:05 -0800101/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700102 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800103 ===========================================================================*/
104
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700105/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800106 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
107 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700108 */
109
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700111static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700112DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800115 /* Limit in DecodeNesting_Descend against more than
116 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700118 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119}
120
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700121
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700122static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700123DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800126 /* Limit in DecodeNesting_Descend against more than
127 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700128 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700129 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700130}
131
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700132
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700133static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700134DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700135{
136 return pNesting->pCurrentBounded->u.ma.uStartOffset;
137}
138
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700139
Laurence Lundblade085d7952020-07-24 10:26:30 -0700140static inline bool
141DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
142{
143 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
144 return true;
145 } else {
146 return false;
147 }
148}
149
150
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700151static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700155 return true;
156 } else {
157 return false;
158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159}
160
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700161
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700162static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700163DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164{
165 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800166 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return false;
168 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800169
170#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700171 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade6474c982020-12-26 22:14:34 -0800178 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700179 return true;
180}
181
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700182static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700183DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700184{
185 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800186 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700193static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
196 return true;
197 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700198 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700199 return true;
200 }
201 return false;
202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700205static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800209 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
210 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
211 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700214
215 if(bIsEmpty) {
216 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
217 }
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 void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700223 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224}
225
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700226
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700227static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229{
230 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800231 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return false;
233 }
234 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800235 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700238 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800242 /* Works for both definite and indefinite length maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800243 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
244 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800248 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700249 return true;
250}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700253static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700254DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800256 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
258 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700259 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700260 return false;
261 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700262}
263
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700264
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700265static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700266DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
269 return true;
270 } else {
271 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700272 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273}
274
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700275
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700276static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700277DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700279 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700280 return false;
281 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282
283 if(pNesting->pCurrentBounded->uLevelType != uType) {
284 return false;
285 }
286
287 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700288}
289
Laurence Lundblade02625d42020-06-25 14:41:41 -0700290
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700291static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700292DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700293{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800294 /* Only call on a defnite length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700295 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700296}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700297
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700299static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
301{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800302 /* Only call on a defnite length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700303 pNesting->pCurrent->u.ma.uCountCursor++;
304}
305
306
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700307static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700308DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
309{
310 pNesting->pCurrent--;
311}
312
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313
314static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700315DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700316{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800317 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700318 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700319 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 }
321
Laurence Lundblade6474c982020-12-26 22:14:34 -0800322 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 pNesting->pCurrent++;
324
325 pNesting->pCurrent->uLevelType = uType;
326
327 return QCBOR_SUCCESS;
328}
329
330
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700331static inline QCBORError
Laurence Lundblade6474c982020-12-26 22:14:34 -0800332DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
333 bool bIsEmpty,
334 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700335{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700336 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800337 * Should only be called on map/array.
338 *
339 * Have descended into this before this is called. The job here is
340 * just to mark it in bounded mode.
341 *
342 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800343 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
344 *
345 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800347 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700348 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349 }
350
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700351 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700352
353 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700354
355 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700356}
357
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700358
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700359static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 uint8_t uQCBORType,
362 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366 if(uCount == 0) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800367 /* Nothing to do for empty definite lenth arrays. They are just are
368 * effectively the same as an item that is not a map or array.
369 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
Laurence Lundblade6474c982020-12-26 22:14:34 -0800371 /* Empty indefinite length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade6474c982020-12-26 22:14:34 -0800374 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
376 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700377 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700381 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383 goto Done;
384 }
385
Laurence Lundblade6474c982020-12-26 22:14:34 -0800386 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700387 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
388 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389
390 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700391
392Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 return uError;;
394}
395
396
397static inline void
398DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
401}
402
403
404static inline void
405DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
406{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 pNesting->pCurrentBounded--;
409 if(DecodeNesting_IsCurrentBounded(pNesting)) {
410 break;
411 }
412 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413}
414
Laurence Lundblade6474c982020-12-26 22:14:34 -0800415
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416static inline void
417DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
418{
419 pNesting->pCurrent = pNesting->pCurrentBounded;
420}
421
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700422
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700423static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700425 uint32_t uEndOffset,
426 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700428 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700430 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432 goto Done;
433 }
434
Laurence Lundblade6474c982020-12-26 22:14:34 -0800435 /* Fill in the new byte string level */
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700436 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
437 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438
Laurence Lundblade6474c982020-12-26 22:14:34 -0800439 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700440 pNesting->pCurrentBounded = pNesting->pCurrent;
441
442Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443 return uError;;
444}
445
Laurence Lundbladed0304932020-06-27 10:59:38 -0700446
447static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700449{
450 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700451}
452
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700453
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700454static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
456{
457 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
458}
459
460
461static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
466 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467}
468
469
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700470static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800471DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
472 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700473{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700474 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700475 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800476 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700477}
478
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700479
Laurence Lundblade02625d42020-06-25 14:41:41 -0700480static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800481DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
482 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700483{
484 *pNesting = *pSave;
485}
486
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487
Laurence Lundblade02625d42020-06-25 14:41:41 -0700488static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700490{
491 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
492}
493
494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700496DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700497{
498 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
499}
500
501
Laurence Lundblade6474c982020-12-26 22:14:34 -0800502
503
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800504#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
507
508 The following four functions are pretty wrappers for invocation of
509 the string allocator supplied by the caller.
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800514StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515{
516 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
517}
518
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519// StringAllocator_Reallocate called with pMem NULL is
520// equal to StringAllocator_Allocate()
521static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800522StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 void *pMem,
524 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800530StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531{
532 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
533}
534
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800536StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537{
538 if(pMe->pfAllocator) {
539 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
540 }
541}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800542#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
544
Laurence Lundblade6474c982020-12-26 22:14:34 -0800545
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547/*===========================================================================
548 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800550 See qcbor/qcbor_decode.h for definition of the object
551 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800552 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800554 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556void QCBORDecode_Init(QCBORDecodeContext *me,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
560 memset(me, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800562 /* Don't bother with error check on decode mode. If a bad value is
563 * passed it will just act as if the default normal mode of 0 was set.
564 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700565 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700566 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700567 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700568 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700569 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570}
571
572
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800573#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
574
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700575/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800576 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
579 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800580 void *pAllocateContext,
581 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700582{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
584 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
585 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800587#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700588
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589
Laurence Lundblade6474c982020-12-26 22:14:34 -0800590
591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800593 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800595void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700597{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800598 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700599 (void)pMe;
600 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601}
602
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700603
Laurence Lundblade1c929722020-12-27 02:44:57 -0800604/**
605 * @brief Decode the CBOR head, the type and argument.
606 *
607 * @param[in] pUInBuf The input buffer to read from.
608 * @param[out] pnMajorType The decoded major type.
609 * @param[out] puArgument The decoded argument.
610 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
611 *
612 * @retval QCBOR_ERR_UNSUPPORTED
613 * @retval QCBOR_ERR_HIT_END
614 *
615 * This decodes the CBOR "head" that every CBOR data item has. See
616 * longer explaination of the head in documentation for
617 * QCBOREncode_EncodeHead().
618 *
619 * This does the network->host byte order conversion. The conversion
620 * here also results in the conversion for floats in addition to that
621 * for lengths, tags and integer values.
622 *
623 * The int type is preferred to uint8_t for some variables as this
624 * avoids integer promotions, can reduce code size and makes static
625 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800627static inline QCBORError
628DecodeHead(UsefulInputBuf *pUInBuf,
629 int *pnMajorType,
630 uint64_t *puArgument,
631 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800633 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundblade1c929722020-12-27 02:44:57 -0800635 /* Get the initial byte that every CBOR data item has and break it
636 * down. */
637 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 const int nTmpMajorType = nInitialByte >> 5;
639 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundblade1c929722020-12-27 02:44:57 -0800641 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800644 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800645 /* Need to get 1,2,4 or 8 additional argument bytes. Map
646 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
647 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800648 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundblade1c929722020-12-27 02:44:57 -0800650 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800651 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800653 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800654 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
655 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800657 /* The reserved and thus-far unused additional info values */
658 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 goto Done;
660 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800661 /* Less than 24, additional info is argument or 31, an
662 * indefinite length. No more bytes to get.
663 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800668 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 goto Done;
670 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671
Laurence Lundblade1c929722020-12-27 02:44:57 -0800672 /* All successful if arrived here. */
673 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800676 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800677
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800679 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680}
681
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682
Laurence Lundblade1c929722020-12-27 02:44:57 -0800683/**
684 * @brief Decode integer types, major types 0 and 1.
685 *
686 * @param[in] nMajorType The CBOR major type (0 or 1).
687 * @param[in] uArgument The argument from the head.
688 * @param[out] pDecodedItem The filled in decoded item.
689 *
690 * @retval QCBOR_ERR_INT_OVERFLOW
691 *
692 * Must only be called when major type is 0 or 1.
693 *
694 * CBOR doesn't explicitly specify two's compliment for integers but
695 * all CPUs use it these days and the test vectors in the RFC are
696 * so. All integers in the CBOR structure are positive and the major
697 * type indicates positive or negative. CBOR can express positive
698 * integers up to 2^x - 1 where x is the number of bits and negative
699 * integers down to 2^x. Note that negative numbers can be one more
700 * away from zero than positive. Stdint, as far as I can tell, uses
701 * two's compliment to represent negative integers.
702 *
703 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
704 * used carefully here, and in particular why it isn't used in the
705 * public interface. Also see
706 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
707 *
708 * Int is used for values that need less than 16-bits and would be
709 * subject to integer promotion and result in complaining from static
710 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700712static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800713DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800715 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800718 if (uArgument <= INT64_MAX) {
719 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800723 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800728 if(uArgument <= INT64_MAX) {
729 /* CBOR's representation of negative numbers lines up with
730 * the two-compliment representation. A negative integer has
731 * one more in range than a positive integer. INT64_MIN is
732 * equal to (-INT64_MAX) - 1.
733 */
734 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800736
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800738 /* C can't represent a negative integer in this range so it
739 * is an error.
740 */
741 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
743 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundblade1c929722020-12-27 02:44:57 -0800745 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746}
747
Laurence Lundblade1c929722020-12-27 02:44:57 -0800748
Laurence Lundblade38299092020-12-28 04:13:50 -0800749/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
751#error QCBOR_TYPE_FALSE macro value wrong
752#endif
753
754#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
755#error QCBOR_TYPE_TRUE macro value wrong
756#endif
757
758#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
759#error QCBOR_TYPE_NULL macro value wrong
760#endif
761
762#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
763#error QCBOR_TYPE_UNDEF macro value wrong
764#endif
765
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700766#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
767#error QCBOR_TYPE_BREAK macro value wrong
768#endif
769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
771#error QCBOR_TYPE_DOUBLE macro value wrong
772#endif
773
774#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
775#error QCBOR_TYPE_FLOAT macro value wrong
776#endif
777
Laurence Lundblade38299092020-12-28 04:13:50 -0800778
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800779/**
780 * @brief Decode type 7 -- true, false, floating-point, break...
781 *
782 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
783 * @param[in] uArgument The argument from the head.
784 * @param[out] pDecodedItem The filled in decoded item.
785 *
786 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
787 * @retval QCBOR_ERR_BAD_TYPE_7
788 */
Laurence Lundblade9b334962020-08-27 10:55:53 -0700789
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700790static inline QCBORError
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800791DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792{
Laurence Lundblade38299092020-12-28 04:13:50 -0800793 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundblade38299092020-12-28 04:13:50 -0800795 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
796 * checks above make sure uAdditionalInfo values line up with
797 * uDataType values. DecodeHead() never returns an AdditionalInfo
798 * > 0x1f so cast is safe.
799 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800802 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800803 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
804 * are caught before this is called.
805 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundblade38299092020-12-28 04:13:50 -0800807 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700808#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800809 /* Half-precision is returned as a double. The cast to
810 * uint16_t is safe because the encoded value was 16 bits. It
811 * was widened to 64 bits to be passed in here.
812 */
813 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700814 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800815#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800816 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800817#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700818 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800819 case SINGLE_PREC_FLOAT: /* 26 */
820 /* Single precision is normally returned as a double since
821 * double is widely supported, there is no loss of precision,
822 * it makes it easy for the caller in most cases and it can
823 * be converted back to single with no loss of precision
824 *
825 * The cast to uint32_t is safe because the encoded value was
826 * 32 bits. It was widened to 64 bits to be passed in here.
827 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700828 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800829 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700830#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800831 /* In the normal case, use HW to convert float to
832 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700833 pDecodedItem->val.dfnum = (double)f;
834 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800835#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800836 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700837 pDecodedItem->val.fnum = f;
838 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
839
Laurence Lundblade38299092020-12-28 04:13:50 -0800840 /* IEEE754_FloatToDouble() could be used here to return as
841 * a double, but it adds object code and most likely
842 * anyone disabling FLOAT HW use doesn't care about floats
843 * and wants to save object code.
844 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800845#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700846 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700847 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700848
Laurence Lundblade38299092020-12-28 04:13:50 -0800849 case DOUBLE_PREC_FLOAT: /* 27 */
850 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700851 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700852 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade38299092020-12-28 04:13:50 -0800854 case CBOR_SIMPLEV_FALSE: /* 20 */
855 case CBOR_SIMPLEV_TRUE: /* 21 */
856 case CBOR_SIMPLEV_NULL: /* 22 */
857 case CBOR_SIMPLEV_UNDEF: /* 23 */
858 case CBOR_SIMPLE_BREAK: /* 31 */
859 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800860
Laurence Lundblade38299092020-12-28 04:13:50 -0800861 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
862 if(uArgument <= CBOR_SIMPLE_BREAK) {
863 /* This takes out f8 00 ... f8 1f which should be encoded
864 * as e0 … f7
865 */
866 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 goto Done;
868 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800869 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundblade38299092020-12-28 04:13:50 -0800871 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800873 /* DecodeHead() will make uArgument equal to
874 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
875 * safe because the 2, 4 and 8 byte lengths of uNumber are in
876 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800877 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800878 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879 break;
880 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700882Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800883 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884}
885
886
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800887/**
888 * @brief Decode text and byte strings
889 *
890 * @param[in] pAllocator The string allocator or NULL.
891 * @param[in] uStrLen The length of the string.
892 * @param[in] pUInBuf The surce from which to read the string's bytes.
893 * @param[out] pDecodedItem The filled in decoded item.
894 *
895 * @retval QCBOR_ERR_HIT_END
896 * @retval QCBOR_ERR_STRING_ALLOCATE
897 * @retval QCBOR_ERR_STRING_TOO_LONG
898 *
899 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
900 * pDecodedItem. If @c pAllocator is not NULL then memory for the
901 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700902 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800903static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800904DecodeBytes(const QCBORInternalAllocator *pAllocator,
905 uint64_t uStrLen,
906 UsefulInputBuf *pUInBuf,
907 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700908{
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800909 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800910
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800911 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
912 * CPUs. This check makes the casts to size_t below safe.
913 *
914 * The max is 4 bytes less than the largest sizeof() so this can be
915 * tested by putting a SIZE_MAX length in the CBOR test input (no
916 * one will care the limit on strings is 4 bytes shorter).
917 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800918 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800919 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800920 goto Done;
921 }
922
923 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530924 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800925 /* Failed to get the bytes for this string item */
926 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530927 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530929
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800930#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800931 /* Note that this is not where allocation to coallsece
932 * indefinite-length strings is done. This is for when the caller
933 * has requested all strings be allocated. Disabling indefinite
934 * length strings also disables this allocate-all option.
935 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800936 if(pAllocator) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800937 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800938 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530939 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800940 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530941 goto Done;
942 }
943 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800944 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800945 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530946 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800947#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
948 (void)pAllocator;
949#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
950
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800951 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800952 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530954Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800955 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956}
957
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800959/**
960 * @brief Map the CBOR major types for strings to the QCBOR types.
961 *
962 * @param[in] nCBORMajorType The CBOR major type to convert.
963 * @retturns QCBOR type number.
964 *
965 * This only works for the two string types.
966 */
967static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800968{
969 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
970 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
971 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800973 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
974 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
975 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800977 return (uint8_t)(nCBORMajorType + 4);
978}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979
980
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800981/**
982 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
983 *
984 * @param[in] nCBORMajorType The CBOR major type to convert.
985 * @retturns QCBOR type number.
986 *
987 * This only works for the two aggregate types.
988 */
989static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
990{
991 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
992 #error QCBOR_TYPE_ARRAY value not lined up with major type
993 #endif
994
995 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
996 #error QCBOR_TYPE_MAP value not lined up with major type
997 #endif
998
999 return (uint8_t)(nCBORMajorType);
1000}
1001
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001003/*
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001004 * @brief Decode a single primitive data item.
1005 *
1006 * @param[in] pUInBuf Input buffer to read data item from.
1007 * @param[ou] pDecodedItem The filled-in decoded item.
1008 * @param[in] pAllocator The allocator to use for strings or NULL.
1009 *
1010 * @retval QCBOR_ERR_UNSUPPORTED
1011 * @retval QCBOR_ERR_HIT_END
1012 * @retval QCBOR_ERR_INT_OVERFLOW
1013 * @retval QCBOR_ERR_STRING_ALLOCATE
1014 * @retval QCBOR_ERR_STRING_TOO_LONG
1015 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1016 * @retval QCBOR_ERR_BAD_TYPE_7
1017 *
1018 * This gets a single data item and decodes it including preceding
1019 * optional tagging. This does not deal with arrays and maps and
1020 * nesting except to decode the data item introducing them. Arrays and
1021 * maps are handled at the next level up in GetNext().
1022 *
1023 * Errors detected here include: an array that is too long to decode,
1024 * hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001025 */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001026static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
1027 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001028 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029{
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001030 QCBORError uReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001031
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001032 /* Get the major type and the argument. The argument could be
1033 * length of more bytes or the value depending on the major
1034 * type. nAdditionalInfo is an encoding of the length of the
1035 * uNumber and is needed to decode floats and doubles.
1036 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001037 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001038 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001039 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001041 memset(pDecodedItem, 0, sizeof(QCBORItem));
1042
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001043 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1044 if(uReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001046 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001047
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001048 /* At this point the major type and the argument are valid. We've
1049 * got the type and the argument that starts every CBOR data item.
1050 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001051 switch (nMajorType) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001052 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1053 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001054 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001055 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001056 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001057 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001058 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001060
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001061 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1062 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1063 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001064 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001065 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001067 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068 }
1069 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001071 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1072 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001073 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001074 /* Indefinite-length string. */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001075#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001076 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001077#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001078 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001079 break;
1080#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001082 /* Definite-length string. */
1083 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1084 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1085 goto Done;
1086 }
1087 /* cast OK because of check above */
Laurence Lundblade1c929722020-12-27 02:44:57 -08001088 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 }
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001090 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001093 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001094 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001095 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001096 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001097 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001098 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001099 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001100 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001101
Laurence Lundbladeee851742020-01-08 08:37:05 -08001102 case CBOR_MAJOR_TYPE_SIMPLE:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001103 /* Major type 7: float, double, true, false, null... */
1104 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001105 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001106
Laurence Lundbladeee851742020-01-08 08:37:05 -08001107 default:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001108 /* Never happens because DecodeHead() should never return > 7 */
1109 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001110 break;
1111 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001112
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001114 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115}
1116
1117
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001118/**
1119 * @brief Process indefinite length strings
1120 *
1121 * @param[in] pMe Decoder context
1122 * @param[in,out] pDecodedItem The decoded item that work is done on.
1123 *
1124 * @retval QCBOR_ERR_UNSUPPORTED
1125 * @retval QCBOR_ERR_HIT_END
1126 * @retval QCBOR_ERR_INT_OVERFLOW
1127 * @retval QCBOR_ERR_STRING_ALLOCATE
1128 * @retval QCBOR_ERR_STRING_TOO_LONG
1129 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1130 * @retval QCBOR_ERR_BAD_TYPE_7
1131 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1132 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1133 *
1134 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1135 *
1136 * If it is, this loops getting the subsequent chunks that make up the
1137 * string. The string allocator is used to make a contiguous buffer for
1138 * the chunks. When this completes @c pDecodedItem contains the
1139 * put-together string.
1140 *
1141 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001143static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001144GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001146 /* Aproximate stack usage
1147 * 64-bit 32-bit
1148 * local vars 32 16
1149 * 2 UsefulBufs 32 16
1150 * QCBORItem 56 52
1151 * TOTAL 120 74
1152 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001153
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001154 /* The string allocator is used here for two purposes: 1)
1155 * coalescing the chunks of an indefinite length string, 2)
1156 * allocating storage for every string returned.
1157 *
1158 * The first use is below in this function. Indefinite length
1159 * strings cannot be processed at all without a string allocator.
1160 *
1161 * The second used is in DecodeBytes() which is called by
1162 * GetNext_Item() below. This second use unneccessary for most use
1163 * and only happens when requested in the call to
1164 * QCBORDecode_SetMemPool(). If the second use not requested then
1165 * NULL is passed for the string allocator to GetNext_Item().
1166 *
1167 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1168 * allocator altogether and thus both of these uses. It reduced the
1169 * decoder object code by about 400 bytes.
1170 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001171 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001172
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001173#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001174 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001175
1176 if(pMe->StringAllocator.pfAllocator) {
1177 pAllocator = &(pMe->StringAllocator);
1178 if(pMe->bStringAllocateAll) {
1179 pAllocatorForGetNext = pAllocator;
1180 }
1181 }
1182#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1183
1184 QCBORError uReturn;
1185 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1186 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001187 goto Done;
1188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001189
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001190 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001191 const uint8_t uStringType = pDecodedItem->uDataType;
1192 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001193 goto Done;
1194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001195
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001196 /* Is this a string with an indefinite length? */
1197 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1198 goto Done;
1199 }
1200
1201#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1202 /* Can't do indefinite length strings without a string allocator */
1203 if(pAllocator == NULL) {
1204 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1205 goto Done;
1206 }
1207
1208 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001209 UsefulBufC FullString = NULLUsefulBufC;
1210
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001211 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001212 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001213 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001214 /* Pass a NULL string allocator to GetNext_Item() because the
1215 * individual string chunks in an indefinite length should not
1216 * be allocated. They are always copied in the the contiguous
1217 * buffer allocated here.
1218 */
1219 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1220 if(uReturn) {
1221 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001222 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001223
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001224 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001225 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001226 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001227 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301228 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001229 break;
1230 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001231
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001232 /* All chunks must be of the same type, the type of the item
1233 * that introduces the indefinite length string. This also
1234 * catches errors where the chunk is not a string at all and an
1235 * indefinite length string inside an indefinite length string.
1236 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001237 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001238 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1239 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001240 break;
1241 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001243 /* The first time throurgh FullString.ptr is NULL and this is
1244 * equivalent to StringAllocator_Allocate(). Subsequently it is
1245 * not NULL and a reallocation happens.
1246 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001247 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1248 UNCONST_POINTER(FullString.ptr),
1249 FullString.len + StringChunkItem.val.string.len);
1250
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001251 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001252 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001253 break;
1254 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001255
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001256 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001257 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001259
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001260 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1261 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001262 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001263 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001264#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1265 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1266#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001267
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001268Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001269 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001270}
1271
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001272
Laurence Lundblade9b334962020-08-27 10:55:53 -07001273static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001274 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001275 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001276 } else if(uTagVal == CBOR_TAG_INVALID16) {
1277 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001279 // This won't be negative because of code below in GetNext_TaggedItem()
1280 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1281 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 }
1283}
1284
Laurence Lundblade9b334962020-08-27 10:55:53 -07001285
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001286/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001287 Gets all optional tag data items preceding a data item that is not an
1288 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001289
1290 @retval QCBOR_ERR_UNSUPPORTED
1291
1292 @retval QCBOR_ERR_HIT_END
1293
1294 @retval QCBOR_ERR_INT_OVERFLOW
1295
1296 @retval QCBOR_ERR_STRING_ALLOCATE
1297
1298 @retval QCBOR_ERR_STRING_TOO_LONG
1299
1300 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1301
1302 @retval QCBOR_ERR_BAD_TYPE_7
1303
1304 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1305
1306 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1307
1308 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001309 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001310static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001311GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001312{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001313 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1314 CBOR_TAG_INVALID16,
1315 CBOR_TAG_INVALID16,
1316 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001317
Laurence Lundblade9b334962020-08-27 10:55:53 -07001318 QCBORError uReturn = QCBOR_SUCCESS;
1319
Laurence Lundblade59289e52019-12-30 13:44:37 -08001320 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001321 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001322 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1323 if(uErr != QCBOR_SUCCESS) {
1324 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001325 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001326 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundblade9b334962020-08-27 10:55:53 -07001328 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001329 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001330 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001331 break;
1332 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001333
Laurence Lundblade9b334962020-08-27 10:55:53 -07001334 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1335 // No room in the tag list
1336 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1337 // Continue on to get all tags on this item even though
1338 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001339 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001340 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001341 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001342 // Slide tags over one in the array to make room at index 0
1343 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1344 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001345 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001346
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001347 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001348 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001349 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001350 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001351 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001352 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001353 break;
1354 }
1355 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1356 break;
1357 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001358 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001359 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1360 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001361 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1362 // Continue on to get all tags on this item even though
1363 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001364 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001365 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001366 }
1367
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001368 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001369 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001370 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001371
1372 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001373 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001374 }
1375 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001376
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001377Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001378 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001379}
1380
1381
1382/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001383 This layer takes care of map entries. It combines the label and data
1384 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001385
1386 @retval QCBOR_ERR_UNSUPPORTED
1387
1388 @retval QCBOR_ERR_HIT_END
1389
1390 @retval QCBOR_ERR_INT_OVERFLOW
1391
1392 @retval QCBOR_ERR_STRING_ALLOCATE
1393
1394 @retval QCBOR_ERR_STRING_TOO_LONG
1395
1396 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1397
1398 @retval QCBOR_ERR_BAD_TYPE_7
1399
1400 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1401
1402 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1403
1404 @retval QCBOR_ERR_TOO_MANY_TAGS
1405
1406 @retval QCBOR_ERR_MAP_LABEL_TYPE
1407
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001408 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001409 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001410static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001411GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001412{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001413 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001414 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001415 if(nReturn)
1416 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001417
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001418 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001419 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001420 goto Done;
1421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001422
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001423 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1424 // In a map and caller wants maps decoded, not treated as arrays
1425
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001426 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001427 // If in a map and the right decoding mode, get the label
1428
Laurence Lundbladeee851742020-01-08 08:37:05 -08001429 // Save label in pDecodedItem and get the next which will
1430 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001431 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001432 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001433 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001434 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001435 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001436
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301437 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001438
1439 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1440 // strings are always good labels
1441 pDecodedItem->label.string = LabelItem.val.string;
1442 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1443 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001444 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001445 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1446 goto Done;
1447 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1448 pDecodedItem->label.int64 = LabelItem.val.int64;
1449 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1450 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1451 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1452 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1453 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1454 pDecodedItem->label.string = LabelItem.val.string;
1455 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1456 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1457 } else {
1458 // label is not an int or a string. It is an arrray
1459 // or a float or such and this implementation doesn't handle that.
1460 // Also, tags on labels are ignored.
1461 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1462 goto Done;
1463 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001464 }
1465 } else {
1466 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001467 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001468 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001469 goto Done;
1470 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001471 // Decoding a map as an array
1472 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001473 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1474 // Cast is needed because of integer promotion
1475 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001476 }
1477 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001478
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001479Done:
1480 return nReturn;
1481}
1482
1483
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001484#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001485/*
1486 See if next item is a CBOR break. If it is, it is consumed,
1487 if not it is not consumed.
1488*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001489static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001490NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1491{
1492 *pbNextIsBreak = false;
1493 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001494 QCBORItem Peek;
1495 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1496 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1497 if(uReturn != QCBOR_SUCCESS) {
1498 return uReturn;
1499 }
1500 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001501 // It is not a break, rewind so it can be processed normally.
1502 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001503 } else {
1504 *pbNextIsBreak = true;
1505 }
1506 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001507
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001508 return QCBOR_SUCCESS;
1509}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001510#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001511
1512
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001513/*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001514 * An item was just consumed, now figure out if it was the
1515 * end of an array/map map that can be closed out. That
1516 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001517*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001518static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001519{
1520 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001521
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001522 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001523 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1524
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001525 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1526 /* Nesting level is bstr-wrapped CBOR */
1527
1528 /* Ascent for bstr-wrapped CBOR is always by explicit call
1529 * so no further ascending can happen.
1530 */
1531 break;
1532
1533 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1534 /* Level is a definite-length array/map */
1535
1536 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001537 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1538 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001539 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001540 break;
1541 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001542 /* All items in a definite length array were consumed so it
1543 * is time to ascend one level. This happens below.
1544 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001545
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001546#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001547 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001548 /* Level is an indefinite-length array/map. */
1549
1550 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001551 bool bIsBreak = false;
1552 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1553 if(uReturn != QCBOR_SUCCESS) {
1554 goto Done;
1555 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001556
1557 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001558 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001559 break;
1560 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001561
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001562 /* It was a break in an indefinite length map / array so
1563 * it is time to ascend one level.
1564 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001565
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001566#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001567 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001568
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001569
1570 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001571
Laurence Lundblade93d89472020-10-03 22:30:50 -07001572 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001573 * QCBORDecode_ExitBoundedMode().
1574 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001575 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001576 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001577 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001578 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001579 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001580 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001581
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001582 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001583 break;
1584 }
1585
1586 /* Finally, actually ascend one level. */
1587 DecodeNesting_Ascend(&(pMe->nesting));
1588 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001589
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001590 uReturn = QCBOR_SUCCESS;
1591
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001592#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001593Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001594#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1595
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001596 return uReturn;
1597}
1598
1599
1600/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001601 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001602 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1603 indefinte length maps and arrays by looking at the item count or
1604 finding CBOR breaks. It detects the ends of the top-level sequence
1605 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001606
1607 @retval QCBOR_ERR_UNSUPPORTED X
1608
1609 @retval QCBOR_ERR_HIT_END
1610
1611 @retval QCBOR_ERR_INT_OVERFLOW X
1612
1613 @retval QCBOR_ERR_STRING_ALLOCATE
1614
1615 @retval QCBOR_ERR_STRING_TOO_LONG
1616
1617 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1618
1619 @retval QCBOR_ERR_BAD_TYPE_7 X
1620
1621 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1622
1623 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1624
1625 @retval QCBOR_ERR_TOO_MANY_TAGS
1626
1627 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1628
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001629 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001630
1631 @retval QCBOR_ERR_NO_MORE_ITEMS
1632
1633 @retval QCBOR_ERR_BAD_BREAK
1634
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001635 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001636static QCBORError
1637QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001638{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001639 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001640 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundblade642282a2020-06-23 12:00:33 -07001642 /*
1643 If out of bytes to consume, it is either the end of the top-level
1644 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001645
Laurence Lundblade642282a2020-06-23 12:00:33 -07001646 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1647 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1648 CBOR is exited, the length is set back to the top-level's length
1649 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001650 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001651 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001652 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001653 goto Done;
1654 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001655
Laurence Lundblade642282a2020-06-23 12:00:33 -07001656 /*
1657 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001658 array. The check for a break ending indefinite length array is
1659 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001660 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001661 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001662 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001663 goto Done;
1664 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001665
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001666 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001667 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001668 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1669 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001670 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001671 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301672
Laurence Lundblade642282a2020-06-23 12:00:33 -07001673 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001674 Breaks ending arrays/maps are processed later in the call to
1675 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001676 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301677 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001678 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301679 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301680 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001681
Laurence Lundblade642282a2020-06-23 12:00:33 -07001682 /*
1683 Record the nesting level for this data item before processing any
1684 of decrementing and descending.
1685 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001686 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001687
Laurence Lundblade642282a2020-06-23 12:00:33 -07001688
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001689 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001690 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001691 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001692 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001693
Laurence Lundblade93d89472020-10-03 22:30:50 -07001694 Empty indefinite length maps and arrays are descended into, but
1695 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001696
1697 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001698 encloses them so a decrement needs to be done for them too, but
1699 that is done only when all the items in them have been
1700 processed, not when they are opened with the exception of an
1701 empty map or array.
1702 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001703 QCBORError uDescendErr;
1704 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001705 pDecodedItem->uDataType,
1706 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001707 if(uDescendErr != QCBOR_SUCCESS) {
1708 /* This error is probably a traversal error and it
1709 overrides the non-traversal error. */
1710 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001711 goto Done;
1712 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001713 }
1714
Laurence Lundblade02625d42020-06-25 14:41:41 -07001715 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1716 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1717 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001718 /*
1719 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001720 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001721 - An empty definite length map or array
1722 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001723
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001724 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001725 definite length map/array and break detection for an indefinite
1726 length map/array. If the end of the map/array was reached, then
1727 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001728 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001729 QCBORError uAscendErr;
1730 uAscendErr = NestLevelAscender(me, true);
1731 if(uAscendErr != QCBOR_SUCCESS) {
1732 /* This error is probably a traversal error and it
1733 overrides the non-traversal error. */
1734 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001735 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001736 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301737 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001738
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001739 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001740 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001741 Tell the caller what level is next. This tells them what
1742 maps/arrays were closed out and makes it possible for them to
1743 reconstruct the tree with just the information returned in
1744 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001745 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001746 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001747 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001748 pDecodedItem->uNextNestLevel = 0;
1749 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001750 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001751 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001752
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001753Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001754 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001755}
1756
Laurence Lundblade9b334962020-08-27 10:55:53 -07001757static void ShiftTags(QCBORItem *pDecodedItem)
1758{
1759 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1760 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1761 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1762 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1763}
1764
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001765
Laurence Lundblade9b334962020-08-27 10:55:53 -07001766
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001768 The epoch formatted date. Turns lots of different forms of encoding
1769 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001770 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001771static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001773 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001774
1775 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1776
1777 switch (pDecodedItem->uDataType) {
1778
1779 case QCBOR_TYPE_INT64:
1780 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1781 break;
1782
1783 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001784 // This only happens for CBOR type 0 > INT64_MAX so it is
1785 // always an overflow.
1786 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1787 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788 break;
1789
1790 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001791 case QCBOR_TYPE_FLOAT:
1792#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001793 {
1794 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001795 // conversion to an int64_t to be able to detect doubles that
1796 // are too large to fit into an int64_t. A double has 52
1797 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1798 // to a double actually causes a round up which is bad and
1799 // wrong for the comparison because it will allow conversion
1800 // of doubles that can't fit into a uint64_t. To remedy this
1801 // INT64_MAX - 0x7ff is used as the cutoff point because if
1802 // that value rounds up in conversion to double it will still
1803 // be less than INT64_MAX. 0x7ff is picked because it has 11
1804 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001805 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001806 // INT64_MAX seconds is on the order of 10 billion years, and
1807 // the earth is less than 5 billion years old, so for most
1808 // uses this conversion error won't occur even though doubles
1809 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001810 //
1811 // Without the 0x7ff there is a ~30 minute range of time
1812 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001813 // where this code would go wrong. Some compilers
1814 // will generate warnings or errors without the 0x7ff
1815 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001816 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1817 pDecodedItem->val.dfnum :
1818 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001819 if(isnan(d) ||
1820 d > (double)(INT64_MAX - 0x7ff) ||
1821 d < (double)(INT64_MIN + 0x7ff)) {
1822 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001823 goto Done;
1824 }
1825 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001826 pDecodedItem->val.epochDate.fSecondsFraction =
1827 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001828 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001829#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001830
Laurence Lundbladec7114722020-08-13 05:11:40 -07001831 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001832 goto Done;
1833
Laurence Lundblade9682a532020-06-06 18:33:04 -07001834#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 break;
1836
1837 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001838 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001839 goto Done;
1840 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001841
Laurence Lundblade59289e52019-12-30 13:44:37 -08001842 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1843
1844Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001845 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001846}
1847
1848
1849#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1850/*
1851 Decode decimal fractions and big floats.
1852
1853 When called pDecodedItem must be the array that is tagged as a big
1854 float or decimal fraction, the array that has the two members, the
1855 exponent and mantissa.
1856
1857 This will fetch and decode the exponent and mantissa and put the
1858 result back into pDecodedItem.
1859 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001860static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001861QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1862{
1863 QCBORError nReturn;
1864
1865 // --- Make sure it is an array; track nesting level of members ---
1866 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1867 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1868 goto Done;
1869 }
1870
1871 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001872 // definite length arrays, but not for indefnite. Instead remember
1873 // the nesting level the two integers must be at, which is one
1874 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001875 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1876
1877 // --- Is it a decimal fraction or a bigfloat? ---
1878 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1879 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1880
1881 // --- Get the exponent ---
1882 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001883 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001884 if(nReturn != QCBOR_SUCCESS) {
1885 goto Done;
1886 }
1887 if(exponentItem.uNestingLevel != nNestLevel) {
1888 // Array is empty or a map/array encountered when expecting an int
1889 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1890 goto Done;
1891 }
1892 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1893 // Data arriving as an unsigned int < INT64_MAX has been converted
1894 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1895 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1896 // will be too large for this to handle and thus an error that will
1897 // get handled in the next else.
1898 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1899 } else {
1900 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1901 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1902 goto Done;
1903 }
1904
1905 // --- Get the mantissa ---
1906 QCBORItem mantissaItem;
1907 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1908 if(nReturn != QCBOR_SUCCESS) {
1909 goto Done;
1910 }
1911 if(mantissaItem.uNestingLevel != nNestLevel) {
1912 // Mantissa missing or map/array encountered when expecting number
1913 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1914 goto Done;
1915 }
1916 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1917 // Data arriving as an unsigned int < INT64_MAX has been converted
1918 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1919 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1920 // will be too large for this to handle and thus an error that
1921 // will get handled in an else below.
1922 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001923 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1924 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001925 // Got a good big num mantissa
1926 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1927 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001928 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1929 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1930 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931 } else {
1932 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1933 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1934 goto Done;
1935 }
1936
1937 // --- Check that array only has the two numbers ---
1938 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001939 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001940 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1941 goto Done;
1942 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001943 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001944
1945Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946 return nReturn;
1947}
1948#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1949
1950
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001951static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001952{
1953 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1954 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001955 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001956 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1957 } else {
1958 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001959
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001960 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001961
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001962 return QCBOR_SUCCESS;
1963}
1964
1965
Laurence Lundblade99615302020-11-29 11:19:47 -08001966/*
1967 * Table of CBOR tags whose content is either a text string or a byte
1968 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1969 * of uQCBORtype indicates the content should be a byte string rather
1970 * than a text string
1971 */
1972struct StringTagMapEntry {
1973 uint16_t uTagNumber;
1974 uint8_t uQCBORtype;
1975};
1976
1977#define IS_BYTE_STRING_BIT 0x80
1978#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1979
1980static const struct StringTagMapEntry StringTagMap[] = {
1981 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1982 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1983 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1984 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1985 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1986 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1987 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1988 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1989 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1990 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1991 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1992};
1993
1994
1995/*
1996 * Process the CBOR tags that whose content is a byte string or a text
1997 * string and for which the string is just passed on to the caller.
1998 *
1999 * This maps the CBOR tag to the QCBOR type and checks the content
2000 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002001 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002002 * possible.
2003 *
2004 * This returns QCBOR_SUCCESS if the tag was procssed,
2005 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2006 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2007 */
2008static inline
2009QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002010{
Laurence Lundblade99615302020-11-29 11:19:47 -08002011 /* This only works on tags that were not mapped; no need for other yet */
2012 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2013 return QCBOR_ERR_UNSUPPORTED;
2014 }
2015
2016 unsigned uIndex;
2017 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2018 if(StringTagMap[uIndex].uTagNumber == uTag) {
2019 break;
2020 }
2021 }
2022
2023 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2024 if(uQCBORType == QCBOR_TYPE_NONE) {
2025 /* repurpose this error to mean, not handled here */
2026 return QCBOR_ERR_UNSUPPORTED;
2027 }
2028
2029 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2030 if(uQCBORType & IS_BYTE_STRING_BIT) {
2031 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2032 }
2033
2034 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002035 return QCBOR_ERR_BAD_OPT_TAG;
2036 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002037
Laurence Lundblade99615302020-11-29 11:19:47 -08002038 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002039 return QCBOR_SUCCESS;
2040}
2041
2042
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043/*
Laurence Lundblade99615302020-11-29 11:19:47 -08002044 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2045 * but the whole tag was not decoded. Here, the whole tags (tag number
2046 * and tag content) that are supported by QCBOR are decoded. This is a
2047 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002049static QCBORError
2050QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002052 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002053
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002054 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2055 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002056 goto Done;
2057 }
2058
Laurence Lundblade99615302020-11-29 11:19:47 -08002059 /* When there are no tag numbers for the item, this exits first
2060 * thing and effectively does nothing.
2061 *
2062 * This loops over all the tag numbers accumulated for this item
2063 * trying to decode and interpret them. This stops at the end of
2064 * the list or at the first tag number that can't be interpreted by
2065 * this code. This is effectively a recursive processing of the
2066 * tags number list that handles nested tags.
2067 */
2068 while(1) {
2069 /* Don't bother to unmap tags via QCBORITem.uTags since this
2070 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2071 */
2072 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073
Laurence Lundblade99615302020-11-29 11:19:47 -08002074 if(uTagToProcess == CBOR_TAG_INVALID16) {
2075 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076 break;
2077
Laurence Lundblade99615302020-11-29 11:19:47 -08002078 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002079 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002080
Laurence Lundblade93d89472020-10-03 22:30:50 -07002081#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002082 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2083 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002084 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002085#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002086
Laurence Lundblade99615302020-11-29 11:19:47 -08002087 } else if(uTagToProcess == CBOR_TAG_MIME ||
2088 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002089 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002090
Laurence Lundblade99615302020-11-29 11:19:47 -08002091 } else {
2092 /* See if it is a pass-through byte/text string tag; process if so */
2093 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002094
Laurence Lundblade99615302020-11-29 11:19:47 -08002095 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2096 /* It wasn't a pass-through byte/text string tag so it is
2097 * an unknown tag. This is the exit from the loop on the
2098 * first unknown tag. It is a successful exit.
2099 */
2100 uReturn = QCBOR_SUCCESS;
2101 break;
2102 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002103 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002104
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002105 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002106 /* Error exit from the loop */
2107 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002108 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002109
2110 /* A tag was successfully processed, shift it out of the list of
2111 * tags returned. This is the loop increment.
2112 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002113 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 }
2115
2116Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002117 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002118}
2119
2120
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002121/*
2122 Public function, see header qcbor/qcbor_decode.h file
2123 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002124QCBORError
2125QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2126{
2127 QCBORError uErr;
2128 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2129 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002130 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2131 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2132 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002133 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002134}
2135
2136
2137/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002138 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002139 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002140QCBORError
2141QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2142{
2143 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2144 const UsefulInputBuf Save = pMe->InBuf;
2145
2146 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2147
2148 pMe->nesting = SaveNesting;
2149 pMe->InBuf = Save;
2150
2151 return uErr;
2152}
2153
2154
2155/*
2156 Public function, see header qcbor/qcbor_decode.h file
2157 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002158void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2159{
2160 if(pMe->uLastError != QCBOR_SUCCESS) {
2161 return;
2162 }
2163
2164 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2165}
2166
2167
2168/*
2169 Public function, see header qcbor/qcbor_decode.h file
2170 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002171QCBORError
2172QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2173 QCBORItem *pDecodedItem,
2174 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002175{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002176 QCBORError nReturn;
2177
2178 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2179 if(nReturn != QCBOR_SUCCESS) {
2180 return nReturn;
2181 }
2182
2183 if(pTags != NULL) {
2184 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002185 // Reverse the order because pTags is reverse of
2186 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002187 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2188 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002189 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002190 }
2191 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2192 return QCBOR_ERR_TOO_MANY_TAGS;
2193 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002194 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002195 pTags->uNumUsed++;
2196 }
2197 }
2198
2199 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002200}
2201
2202
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002203/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302204 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302205 next one down. If a layer has no work to do for a particular item
2206 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002207
Laurence Lundblade59289e52019-12-30 13:44:37 -08002208 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2209 tagged data items, turning them into the local C representation.
2210 For the most simple it is just associating a QCBOR_TYPE with the data. For
2211 the complex ones that an aggregate of data items, there is some further
2212 decoding and a little bit of recursion.
2213
2214 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302215 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302216 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002217 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002218
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302219 - GetNext_MapEntry -- This handles the combining of two
2220 items, the label and the data, that make up a map entry.
2221 It only does work on maps. It combines the label and data
2222 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002223
Laurence Lundblade59289e52019-12-30 13:44:37 -08002224 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2225 tags into bit flags associated with the data item. No actual decoding
2226 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundblade59289e52019-12-30 13:44:37 -08002228 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302229 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302230 string allocater to create contiguous space for the item. It
2231 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002232
Laurence Lundblade59289e52019-12-30 13:44:37 -08002233 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2234 atomic data item has a "major type", an integer "argument" and optionally
2235 some content. For text and byte strings, the content is the bytes
2236 that make up the string. These are the smallest data items that are
2237 considered to be well-formed. The content may also be other data items in
2238 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002240 Roughly this takes 300 bytes of stack for vars. Need to
2241 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302243 */
2244
2245
2246/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002247 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002248 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002249bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002250 const QCBORItem *pItem,
2251 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002252{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002253 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2254 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002255 break;
2256 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002257 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002258 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002259 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002260 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002261
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002262 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002263}
2264
2265
2266/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002267 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002268 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002269QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002270{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002271 QCBORError uReturn = me->uLastError;
2272
2273 if(uReturn != QCBOR_SUCCESS) {
2274 goto Done;
2275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002276
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002277 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002278 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002279 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002280 goto Done;
2281 }
2282
2283 // Error out if not all the bytes are consumed
2284 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002285 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002286 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002287
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002288Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002289#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302290 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002291 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002292 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002293#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294
Laurence Lundblade085d7952020-07-24 10:26:30 -07002295 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002296}
2297
2298
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002299/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002300 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002301*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002302// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002303uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2304 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002305 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002306{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002307 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2308 return CBOR_TAG_INVALID64;
2309 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002310 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2311 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002312 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002313 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002314 }
2315}
2316
Laurence Lundblade9b334962020-08-27 10:55:53 -07002317/*
2318 Public function, see header qcbor/qcbor_decode.h file
2319*/
2320uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2321 uint32_t uIndex)
2322{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002323 if(pMe->uLastError != QCBOR_SUCCESS) {
2324 return CBOR_TAG_INVALID64;
2325 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002326 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2327 return CBOR_TAG_INVALID64;
2328 } else {
2329 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2330 }
2331}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002332
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002333/*
2334
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002335Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002336
Laurence Lundbladeee851742020-01-08 08:37:05 -08002337 - Hit end of input before it was expected while decoding type and
2338 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002339
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002340 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002341
Laurence Lundbladeee851742020-01-08 08:37:05 -08002342 - Hit end of input while decoding a text or byte string
2343 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002344
Laurence Lundbladeee851742020-01-08 08:37:05 -08002345 - Encountered conflicting tags -- e.g., an item is tagged both a date
2346 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002347
Laurence Lundbladeee851742020-01-08 08:37:05 -08002348 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002349 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002350
Laurence Lundbladeee851742020-01-08 08:37:05 -08002351 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002352 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002353
Laurence Lundbladeee851742020-01-08 08:37:05 -08002354 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2355 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002356
Laurence Lundbladeee851742020-01-08 08:37:05 -08002357 - The type of a map label is not a string or int
2358 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002359
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002360 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002361
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002362 */
2363
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002364
2365
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002366#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002367
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002368/* ===========================================================================
2369 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002370
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002371 This implements a simple sting allocator for indefinite length
2372 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2373 implements the function type QCBORStringAllocate and allows easy
2374 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002375
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002376 This particular allocator is built-in for convenience. The caller
2377 can implement their own. All of this following code will get
2378 dead-stripped if QCBORDecode_SetMemPool() is not called.
2379
2380 This is a very primitive memory allocator. It does not track
2381 individual allocations, only a high-water mark. A free or
2382 reallocation must be of the last chunk allocated.
2383
2384 The size of the pool and offset to free memory are packed into the
2385 first 8 bytes of the memory pool so we don't have to keep them in
2386 the decode context. Since the address of the pool may not be
2387 aligned, they have to be packed and unpacked as if they were
2388 serialized data of the wire or such.
2389
2390 The sizes packed in are uint32_t to be the same on all CPU types
2391 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002392 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002393
2394
Laurence Lundbladeee851742020-01-08 08:37:05 -08002395static inline int
2396MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002397{
2398 // Use of UsefulInputBuf is overkill, but it is convenient.
2399 UsefulInputBuf UIB;
2400
Laurence Lundbladeee851742020-01-08 08:37:05 -08002401 // Just assume the size here. It was checked during SetUp so
2402 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002403 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002404 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2405 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2406 return UsefulInputBuf_GetError(&UIB);
2407}
2408
2409
Laurence Lundbladeee851742020-01-08 08:37:05 -08002410static inline int
2411MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002412{
2413 // Use of UsefulOutBuf is overkill, but convenient. The
2414 // length check performed here is useful.
2415 UsefulOutBuf UOB;
2416
2417 UsefulOutBuf_Init(&UOB, Pool);
2418 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2419 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2420 return UsefulOutBuf_GetError(&UOB);
2421}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002422
2423
2424/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002425 Internal function for an allocation, reallocation free and destuct.
2426
2427 Having only one function rather than one each per mode saves space in
2428 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002429
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002430 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2431 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002432static UsefulBuf
2433MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002434{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002435 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002436
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002437 uint32_t uPoolSize;
2438 uint32_t uFreeOffset;
2439
2440 if(uNewSize > UINT32_MAX) {
2441 // This allocator is only good up to 4GB. This check should
2442 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2443 goto Done;
2444 }
2445 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2446
2447 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2448 goto Done;
2449 }
2450
2451 if(uNewSize) {
2452 if(pMem) {
2453 // REALLOCATION MODE
2454 // Calculate pointer to the end of the memory pool. It is
2455 // assumed that pPool + uPoolSize won't wrap around by
2456 // assuming the caller won't pass a pool buffer in that is
2457 // not in legitimate memory space.
2458 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2459
2460 // Check that the pointer for reallocation is in the range of the
2461 // pool. This also makes sure that pointer math further down
2462 // doesn't wrap under or over.
2463 if(pMem >= pPool && pMem < pPoolEnd) {
2464 // Offset to start of chunk for reallocation. This won't
2465 // wrap under because of check that pMem >= pPool. Cast
2466 // is safe because the pool is always less than UINT32_MAX
2467 // because of check in QCBORDecode_SetMemPool().
2468 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2469
2470 // Check to see if the allocation will fit. uPoolSize -
2471 // uMemOffset will not wrap under because of check that
2472 // pMem is in the range of the uPoolSize by check above.
2473 if(uNewSize <= uPoolSize - uMemOffset) {
2474 ReturnValue.ptr = pMem;
2475 ReturnValue.len = uNewSize;
2476
2477 // Addition won't wrap around over because uNewSize was
2478 // checked to be sure it is less than the pool size.
2479 uFreeOffset = uMemOffset + uNewSize32;
2480 }
2481 }
2482 } else {
2483 // ALLOCATION MODE
2484 // uPoolSize - uFreeOffset will not underflow because this
2485 // pool implementation makes sure uFreeOffset is always
2486 // smaller than uPoolSize through this check here and
2487 // reallocation case.
2488 if(uNewSize <= uPoolSize - uFreeOffset) {
2489 ReturnValue.len = uNewSize;
2490 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002491 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002492 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002493 }
2494 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002495 if(pMem) {
2496 // FREE MODE
2497 // Cast is safe because of limit on pool size in
2498 // QCBORDecode_SetMemPool()
2499 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2500 } else {
2501 // DESTRUCT MODE
2502 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002503 }
2504 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002505
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002506 UsefulBuf Pool = {pPool, uPoolSize};
2507 MemPool_Pack(Pool, uFreeOffset);
2508
2509Done:
2510 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002511}
2512
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002513
Laurence Lundbladef6531662018-12-04 10:42:22 +09002514/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002515 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002516 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002517QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2518 UsefulBuf Pool,
2519 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002520{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002521 // The pool size and free mem offset are packed into the beginning
2522 // of the pool memory. This compile time check make sure the
2523 // constant in the header is correct. This check should optimize
2524 // down to nothing.
2525 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002526 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002527 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002528
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002529 // The pool size and free offset packed in to the beginning of pool
2530 // memory are only 32-bits. This check will optimize out on 32-bit
2531 // machines.
2532 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002533 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002534 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002535
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002536 // This checks that the pool buffer given is big enough.
2537 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002538 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002539 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002540
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002541 pMe->StringAllocator.pfAllocator = MemPool_Function;
2542 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2543 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002544
Laurence Lundblade30816f22018-11-10 13:40:22 +07002545 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002546}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002547#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002548
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002549
2550
Laurence Lundblade9b334962020-08-27 10:55:53 -07002551static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2552{
2553 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2554}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002555
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002556
2557/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002558 Consume an entire map or array (and do next to
2559 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002561static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002562ConsumeItem(QCBORDecodeContext *pMe,
2563 const QCBORItem *pItemToConsume,
2564 uint_fast8_t *puNextNestLevel)
2565{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002566 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002567 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002568
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002569 // If it is a map or array, this will tell if it is empty.
2570 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2571
2572 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2573 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002574
Laurence Lundblade1341c592020-04-11 14:19:05 -07002575 /* This works for definite and indefinite length
2576 * maps and arrays by using the nesting level
2577 */
2578 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002579 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002580 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002581 goto Done;
2582 }
2583 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002584
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002585 *puNextNestLevel = Item.uNextNestLevel;
2586
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002587 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002588
Laurence Lundblade1341c592020-04-11 14:19:05 -07002589 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002590 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002591 /* Just pass the nesting level through */
2592 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2593
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002594 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002595 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002596
2597Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002598 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002599}
2600
2601
Laurence Lundblade1341c592020-04-11 14:19:05 -07002602/* Return true if the labels in Item1 and Item2 are the same.
2603 Works only for integer and string labels. Returns false
2604 for any other type. */
2605static inline bool
2606MatchLabel(QCBORItem Item1, QCBORItem Item2)
2607{
2608 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2609 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2610 return true;
2611 }
2612 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002613 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002614 return true;
2615 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002616 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002617 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2618 return true;
2619 }
2620 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2621 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2622 return true;
2623 }
2624 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002625
Laurence Lundblade1341c592020-04-11 14:19:05 -07002626 /* Other label types are never matched */
2627 return false;
2628}
2629
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002630
2631/*
2632 Returns true if Item1 and Item2 are the same type
2633 or if either are of QCBOR_TYPE_ANY.
2634 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002635static inline bool
2636MatchType(QCBORItem Item1, QCBORItem Item2)
2637{
2638 if(Item1.uDataType == Item2.uDataType) {
2639 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002640 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002641 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002642 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002643 return true;
2644 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002645 return false;
2646}
2647
2648
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002649/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002650 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002651
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002652 @param[in] pMe The decode context to search.
2653 @param[in,out] pItemArray The items to search for and the items found.
2654 @param[out] puOffset Byte offset of last item matched.
2655 @param[in] pCBContext Context for the not-found item call back.
2656 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002657
2658 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2659
Laurence Lundblade93d89472020-10-03 22:30:50 -07002660 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2661 were found for one of the labels being
2662 search for. This duplicate detection is
2663 only performed for items in pItemArray,
2664 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002665
Laurence Lundblade93d89472020-10-03 22:30:50 -07002666 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2667 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002668
2669 @retval Also errors returned by QCBORDecode_GetNext().
2670
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002671 On input pItemArray contains a list of labels and data types
2672 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002673
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002674 On output the fully retrieved items are filled in with
2675 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002676
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002677 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002678
2679 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002680 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002681static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002682MapSearch(QCBORDecodeContext *pMe,
2683 QCBORItem *pItemArray,
2684 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002685 void *pCBContext,
2686 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002688 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002689 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002690
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002691 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002692 uReturn = pMe->uLastError;
2693 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002694 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002695
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002696 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002697 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2698 /* QCBOR_TYPE_NONE as first item indicates just looking
2699 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002700 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2701 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002702 }
2703
Laurence Lundblade085d7952020-07-24 10:26:30 -07002704 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2705 // It is an empty bounded array or map
2706 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2707 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002708 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002709 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002710 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002711 // Nothing is ever found in an empty array or map. All items
2712 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002713 uReturn = QCBOR_SUCCESS;
2714 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002715 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002716 }
2717
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002718 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002719 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2720
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002721 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002722 UsefulInputBuf_Seek(&(pMe->InBuf),
2723 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002724
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002725 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002726 Loop over all the items in the map or array. Each item
2727 could be a map or array, but label matching is only at
2728 the main level. This handles definite and indefinite
2729 length maps and arrays. The only reason this is ever
2730 called on arrays is to find their end position.
2731
2732 This will always run over all items in order to do
2733 duplicate detection.
2734
2735 This will exit with failure if it encounters an
2736 unrecoverable error, but continue on for recoverable
2737 errors.
2738
2739 If a recoverable error occurs on a matched item, then
2740 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002741 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002742 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002743 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002744 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002745 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002746 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002748 /* Get the item */
2749 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002750 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2751 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002752 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002753 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754 goto Done;
2755 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002756 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002757 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002758 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002759 goto Done;
2760 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002761
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002762 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002763 bool bMatched = false;
2764 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2765 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002766 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002767 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2768 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002769 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002770 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002771 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002772 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002773 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002774 goto Done;
2775 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002776
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002777 if(uResult != QCBOR_SUCCESS) {
2778 uReturn = uResult;
2779 goto Done;
2780 }
2781
Laurence Lundblade1341c592020-04-11 14:19:05 -07002782 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002783 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002784 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002785 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002786 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002788 bMatched = true;
2789 }
2790 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002791
2792
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002793 if(!bMatched && pfCallback != NULL) {
2794 /*
2795 Call the callback on unmatched labels.
2796 (It is tempting to do duplicate detection here, but that would
2797 require dynamic memory allocation because the number of labels
2798 that might be encountered is unbounded.)
2799 */
2800 uReturn = (*pfCallback)(pCBContext, &Item);
2801 if(uReturn != QCBOR_SUCCESS) {
2802 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002803 }
2804 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002805
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002806 /*
2807 Consume the item whether matched or not. This
2808 does the work of traversing maps and array and
2809 everything in them. In this loop only the
2810 items at the current nesting level are examined
2811 to match the labels.
2812 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002813 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002814 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002815 goto Done;
2816 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002817
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002818 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002819
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002820 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002821
2822 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002823
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002824 // Check here makes sure that this won't accidentally be
2825 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002826 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002827 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2828 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002829 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2830 goto Done;
2831 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002832 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2833 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002834
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002835 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002836 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2837
2838 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002839 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002840 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002841 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002842 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2843 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002844 }
2845 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002846
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002847 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002848}
2849
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002850
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002851/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002852 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002853*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002854void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2855 int64_t nLabel,
2856 uint8_t uQcborType,
2857 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002858{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002859 if(pMe->uLastError != QCBOR_SUCCESS) {
2860 return;
2861 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002862
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002863 QCBORItem OneItemSeach[2];
2864 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2865 OneItemSeach[0].label.int64 = nLabel;
2866 OneItemSeach[0].uDataType = uQcborType;
2867 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002868
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002869 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002870
2871 *pItem = OneItemSeach[0];
2872
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002873 if(uReturn != QCBOR_SUCCESS) {
2874 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002875 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002876 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002877 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002878 }
2879
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002880 Done:
2881 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002882}
2883
2884
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002885/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002886 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002887*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002888void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2889 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002890 uint8_t uQcborType,
2891 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002892{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002893 if(pMe->uLastError != QCBOR_SUCCESS) {
2894 return;
2895 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002896
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002897 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002898 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2899 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2900 OneItemSeach[0].uDataType = uQcborType;
2901 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002902
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002903 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2904 if(uReturn != QCBOR_SUCCESS) {
2905 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002906 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002907 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002908 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002909 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002910 }
2911
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002912 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002913
2914Done:
2915 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002916}
2917
2918
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002919
Laurence Lundblade93d89472020-10-03 22:30:50 -07002920static QCBORError
2921CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002922{
2923 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2924 if(uDataType == puTypeList[i]) {
2925 return QCBOR_SUCCESS;
2926 }
2927 }
2928 return QCBOR_ERR_UNEXPECTED_TYPE;
2929}
2930
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002931
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002932/**
2933 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002934 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002935
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002936 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2937 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002938
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002939 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2940 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002941 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002942static QCBORError
2943CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002944{
2945 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2946 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2947 /* There are tags that QCBOR couldn't process on this item and
2948 the caller has told us there should not be. */
2949 return QCBOR_ERR_UNEXPECTED_TYPE;
2950 }
2951
2952 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2953 const int nItemType = pItem->uDataType;
2954
2955 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2956 // Must match the tag and only the tag
2957 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2958 }
2959
2960 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2961 if(uReturn == QCBOR_SUCCESS) {
2962 return QCBOR_SUCCESS;
2963 }
2964
2965 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2966 /* Must match the content type and only the content type.
2967 There was no match just above so it is a fail. */
2968 return QCBOR_ERR_UNEXPECTED_TYPE;
2969 }
2970
2971 /* If here it can match either the tag or the content
2972 and it hasn't matched the content, so the end
2973 result is whether it matches the tag. This is
2974 also the case that the CBOR standard discourages. */
2975
2976 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2977}
2978
Laurence Lundblade9b334962020-08-27 10:55:53 -07002979
Laurence Lundblade9b334962020-08-27 10:55:53 -07002980
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002981// This could be semi-private if need be
2982static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002983void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2984 int64_t nLabel,
2985 TagSpecification TagSpec,
2986 QCBORItem *pItem)
2987{
2988 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2989 if(pMe->uLastError != QCBOR_SUCCESS) {
2990 return;
2991 }
2992
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002993 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002994}
2995
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002996
2997// This could be semi-private if need be
2998static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002999void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3000 const char *szLabel,
3001 TagSpecification TagSpec,
3002 QCBORItem *pItem)
3003{
3004 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3005 if(pMe->uLastError != QCBOR_SUCCESS) {
3006 return;
3007 }
3008
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003009 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003010}
3011
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003012// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003013void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3014 int64_t nLabel,
3015 TagSpecification TagSpec,
3016 UsefulBufC *pString)
3017{
3018 QCBORItem Item;
3019 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3020 if(pMe->uLastError == QCBOR_SUCCESS) {
3021 *pString = Item.val.string;
3022 }
3023}
3024
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003025// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003026void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3027 const char * szLabel,
3028 TagSpecification TagSpec,
3029 UsefulBufC *pString)
3030{
3031 QCBORItem Item;
3032 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3033 if(pMe->uLastError == QCBOR_SUCCESS) {
3034 *pString = Item.val.string;
3035 }
3036}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003037
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003038/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003039 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003040*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003041void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003042{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003043 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3044 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003045}
3046
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003047/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003048 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003049*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003050void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3051 QCBORItem *pItemList,
3052 void *pCallbackCtx,
3053 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003054{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003055 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3056 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003057}
3058
3059
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003060/**
3061 * @brief Search for a map/array by label and enter it
3062 *
3063 * @param[in] pMe The decode context.
3064 * @param[in] pSearch The map/array to search for.
3065 *
3066 * @c pSearch is expected to contain one item of type map or array
3067 * with the label specified. The current bounded map will be searched for
3068 * this and if found will be entered.
3069 *
3070 * If the label is not found, or the item found is not a map or array,
3071 * the error state is set.
3072 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003073static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003074{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003075 // The first item in pSearch is the one that is to be
3076 // entered. It should be the only one filled in. Any other
3077 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003078 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003079 return;
3080 }
3081
3082 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003083 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003084 if(pMe->uLastError != QCBOR_SUCCESS) {
3085 return;
3086 }
3087
Laurence Lundblade9b334962020-08-27 10:55:53 -07003088 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003089 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003090 return;
3091 }
3092
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003093 /*
3094 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3095 * next item for the pre-order traversal cursor to be the map/array
3096 * found by MapSearch(). The next few lines of code force the
3097 * cursor to that.
3098 *
3099 * There is no need to retain the old cursor because
3100 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3101 * beginning of the map/array being entered.
3102 *
3103 * The cursor is forced by: 1) setting the input buffer position to
3104 * the item offset found by MapSearch(), 2) setting the map/array
3105 * counter to the total in the map/array, 3) setting the nesting
3106 * level. Setting the map/array counter to the total is not
3107 * strictly correct, but this is OK because this cursor only needs
3108 * to be used to get one item and MapSearch() has already found it
3109 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003110 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003111 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003112
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003113 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3114
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003115 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003116
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003117 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003118}
3119
3120
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003121/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003122 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003123*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003124void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003125{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003126 QCBORItem OneItemSeach[2];
3127 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3128 OneItemSeach[0].label.int64 = nLabel;
3129 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3130 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003131
Laurence Lundblade9b334962020-08-27 10:55:53 -07003132 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003133 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003134}
3135
3136
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003137/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003138 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003139*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003140void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003141{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003142 QCBORItem OneItemSeach[2];
3143 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3144 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3145 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3146 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003147
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003148 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003149}
3150
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003151/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003152 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003153*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003154void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003155{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003156 QCBORItem OneItemSeach[2];
3157 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3158 OneItemSeach[0].label.int64 = nLabel;
3159 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3160 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003161
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003162 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003163}
3164
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003165/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003166 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003167*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003168void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3169{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003170 QCBORItem OneItemSeach[2];
3171 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3172 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3173 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3174 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003175
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003176 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003177}
3178
3179
Laurence Lundblade02625d42020-06-25 14:41:41 -07003180// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003181void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003182{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003183 QCBORError uErr;
3184
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003185 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003186 if(pMe->uLastError != QCBOR_SUCCESS) {
3187 // Already in error state; do nothing.
3188 return;
3189 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003190
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003191 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003192 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003193 uErr = QCBORDecode_GetNext(pMe, &Item);
3194 if(uErr != QCBOR_SUCCESS) {
3195 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003196 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003197 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003198 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3199 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003200 }
3201
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003202 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003203
3204
Laurence Lundbladef0499502020-08-01 11:55:57 -07003205 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003206 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003207 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3208 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003209 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003210 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3211 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003212 // Special case to increment nesting level for zero-length maps
3213 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003214 DecodeNesting_Descend(&(pMe->nesting), uType);
3215 }
3216
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003217 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003218
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003219 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3220 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003221
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003222 if(pItem != NULL) {
3223 *pItem = Item;
3224 }
3225
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003226Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003227 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003228}
3229
Laurence Lundblade02625d42020-06-25 14:41:41 -07003230
3231/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003232 This is the common work for exiting a level that is a bounded map,
3233 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003234
3235 One chunk of work is to set up the pre-order traversal so it is at
3236 the item just after the bounded map, array or bstr that is being
3237 exited. This is somewhat complex.
3238
3239 The other work is to level-up the bounded mode to next higest bounded
3240 mode or the top level if there isn't one.
3241 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003242static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003243ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003244{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003245 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003246
Laurence Lundblade02625d42020-06-25 14:41:41 -07003247 /*
3248 First the pre-order-traversal byte offset is positioned to the
3249 item just after the bounded mode item that was just consumed.
3250 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003251 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3252
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 /*
3254 Next, set the current nesting level to one above the bounded level
3255 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003256
Laurence Lundblade02625d42020-06-25 14:41:41 -07003257 DecodeNesting_CheckBoundedType() is always called before this and
3258 makes sure pCurrentBounded is valid.
3259 */
3260 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3261
3262 /*
3263 This does the complex work of leveling up the pre-order traversal
3264 when the end of a map or array or another bounded level is
3265 reached. It may do nothing, or ascend all the way to the top
3266 level.
3267 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003268 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003269 if(uErr != QCBOR_SUCCESS) {
3270 goto Done;
3271 }
3272
Laurence Lundblade02625d42020-06-25 14:41:41 -07003273 /*
3274 This makes the next highest bounded level the current bounded
3275 level. If there is no next highest level, then no bounded mode is
3276 in effect.
3277 */
3278 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003279
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003280 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003281
3282Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003283 return uErr;
3284}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003285
Laurence Lundblade02625d42020-06-25 14:41:41 -07003286
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003287// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003288void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003289{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003290 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003291 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003292 return;
3293 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003294
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003296
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003297 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003298 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003299 goto Done;
3300 }
3301
Laurence Lundblade02625d42020-06-25 14:41:41 -07003302 /*
3303 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003304 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003305 from previous map search, then do a dummy search.
3306 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003307 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003308 QCBORItem Dummy;
3309 Dummy.uLabelType = QCBOR_TYPE_NONE;
3310 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3311 if(uErr != QCBOR_SUCCESS) {
3312 goto Done;
3313 }
3314 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003315
Laurence Lundblade02625d42020-06-25 14:41:41 -07003316 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003317
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003318Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003319 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003320}
3321
3322
Laurence Lundblade1341c592020-04-11 14:19:05 -07003323
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003324static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325 const QCBORItem *pItem,
3326 uint8_t uTagRequirement,
3327 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003328{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003329 if(pBstr) {
3330 *pBstr = NULLUsefulBufC;
3331 }
3332
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003333 if(pMe->uLastError != QCBOR_SUCCESS) {
3334 // Already in error state; do nothing.
3335 return pMe->uLastError;
3336 }
3337
3338 QCBORError uError = QCBOR_SUCCESS;
3339
3340 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3341 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3342 goto Done;;
3343 }
3344
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003345 const TagSpecification TagSpec =
3346 {
3347 uTagRequirement,
3348 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3349 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3350 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003351
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003352 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003353 if(uError != QCBOR_SUCCESS) {
3354 goto Done;
3355 }
3356
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003357 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003358 // Reverse the decrement done by GetNext() for the bstr so the
3359 // increment in NestLevelAscender() called by ExitBoundedLevel()
3360 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003361 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003362 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003363
3364 if(pBstr) {
3365 *pBstr = pItem->val.string;
3366 }
3367
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003368 // This saves the current length of the UsefulInputBuf and then
3369 // narrows the UsefulInputBuf to start and length of the wrapped
3370 // CBOR that is being entered.
3371 //
3372 // This makes sure the length is less than
3373 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3374 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3375 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3376 // the casts safe. uEndOfBstr will always be less than
3377 // uPreviousLength because of the way UsefulInputBuf works so there
3378 // is no need to check it. There is also a range check in the
3379 // seek.
3380 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003381 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003382 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003383 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003384 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003385 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003386 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003387 goto Done;
3388 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003389 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003390 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003391 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003392
Laurence Lundblade02625d42020-06-25 14:41:41 -07003393 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003394 (uint32_t)uPreviousLength,
3395 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003396Done:
3397 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003398}
3399
3400
Laurence Lundblade02625d42020-06-25 14:41:41 -07003401/*
3402 Public function, see header qcbor/qcbor_decode.h file
3403 */
3404void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003405 uint8_t uTagRequirement,
3406 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003407{
3408 if(pMe->uLastError != QCBOR_SUCCESS) {
3409 // Already in error state; do nothing.
3410 return;
3411 }
3412
3413 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003414 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003415 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3416 if(pMe->uLastError != QCBOR_SUCCESS) {
3417 return;
3418 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003419
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003420 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003421 &Item,
3422 uTagRequirement,
3423 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003424}
3425
3426
Laurence Lundblade02625d42020-06-25 14:41:41 -07003427/*
3428 Public function, see header qcbor/qcbor_decode.h file
3429 */
3430void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003431 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003432 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003433 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003434{
3435 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003436 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003437
Laurence Lundblade93d89472020-10-03 22:30:50 -07003438 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3439 &Item,
3440 uTagRequirement,
3441 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003442}
3443
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003444
Laurence Lundblade02625d42020-06-25 14:41:41 -07003445/*
3446 Public function, see header qcbor/qcbor_decode.h file
3447 */
3448void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003449 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003450 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003451 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003452{
3453 QCBORItem Item;
3454 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3455
Laurence Lundblade93d89472020-10-03 22:30:50 -07003456 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3457 &Item,
3458 uTagRequirement,
3459 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003460}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003461
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003462
Laurence Lundblade02625d42020-06-25 14:41:41 -07003463/*
3464 Public function, see header qcbor/qcbor_decode.h file
3465 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003466void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003467{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003468 if(pMe->uLastError != QCBOR_SUCCESS) {
3469 // Already in error state; do nothing.
3470 return;
3471 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003472
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003473 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003474 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003475 return;
3476 }
3477
3478 /*
3479 Reset the length of the UsefulInputBuf to what it was before
3480 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003481 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003482 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003483 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003484
3485
Laurence Lundblade02625d42020-06-25 14:41:41 -07003486 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003487 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003488}
3489
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003490
Laurence Lundbladee6430642020-03-14 21:15:44 -07003491
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003492
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003493
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003494
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003495
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003496
Laurence Lundblade93d89472020-10-03 22:30:50 -07003497static QCBORError
3498InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003499{
3500 switch(pItem->uDataType) {
3501 case QCBOR_TYPE_TRUE:
3502 *pBool = true;
3503 return QCBOR_SUCCESS;
3504 break;
3505
3506 case QCBOR_TYPE_FALSE:
3507 *pBool = false;
3508 return QCBOR_SUCCESS;
3509 break;
3510
3511 default:
3512 return QCBOR_ERR_UNEXPECTED_TYPE;
3513 break;
3514 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003515 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003516}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003517
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003518
Laurence Lundblade9b334962020-08-27 10:55:53 -07003519
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003520/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003521 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003522*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003523void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003524{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003525 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003526 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003527 return;
3528 }
3529
Laurence Lundbladec4537442020-04-14 18:53:22 -07003530 QCBORError nError;
3531 QCBORItem Item;
3532
3533 nError = QCBORDecode_GetNext(pMe, &Item);
3534 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003535 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003536 return;
3537 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003538 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003539}
3540
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003541
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003542/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003543 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003544*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003545void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003546{
3547 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003548 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003549
Laurence Lundblade9b334962020-08-27 10:55:53 -07003550 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003551}
3552
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003553
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003554/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003555 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003556*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003557void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3558{
3559 QCBORItem Item;
3560 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3561
Laurence Lundblade9b334962020-08-27 10:55:53 -07003562 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003563}
3564
3565
3566
Laurence Lundbladec7114722020-08-13 05:11:40 -07003567
3568static void ProcessEpochDate(QCBORDecodeContext *pMe,
3569 QCBORItem *pItem,
3570 uint8_t uTagRequirement,
3571 int64_t *pnTime)
3572{
3573 if(pMe->uLastError != QCBOR_SUCCESS) {
3574 // Already in error state, do nothing
3575 return;
3576 }
3577
3578 QCBORError uErr;
3579
3580 const TagSpecification TagSpec =
3581 {
3582 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003583 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3584 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003585 };
3586
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003587 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003588 if(uErr != QCBOR_SUCCESS) {
3589 goto Done;
3590 }
3591
3592 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3593 uErr = DecodeDateEpoch(pItem);
3594 if(uErr != QCBOR_SUCCESS) {
3595 goto Done;
3596 }
3597 }
3598
Laurence Lundblade9b334962020-08-27 10:55:53 -07003599 // Save the tags in the last item's tags in the decode context
3600 // for QCBORDecode_GetNthTagOfLast()
3601 CopyTags(pMe, pItem);
3602
Laurence Lundbladec7114722020-08-13 05:11:40 -07003603 *pnTime = pItem->val.epochDate.nSeconds;
3604
3605Done:
3606 pMe->uLastError = (uint8_t)uErr;
3607}
3608
3609
3610void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003611 uint8_t uTagRequirement,
3612 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003613{
3614 if(pMe->uLastError != QCBOR_SUCCESS) {
3615 // Already in error state, do nothing
3616 return;
3617 }
3618
3619 QCBORItem Item;
3620 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3621
3622 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3623}
3624
3625
3626void
3627QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3628 int64_t nLabel,
3629 uint8_t uTagRequirement,
3630 int64_t *pnTime)
3631{
3632 QCBORItem Item;
3633 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3634 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3635}
3636
3637
3638void
3639QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3640 const char *szLabel,
3641 uint8_t uTagRequirement,
3642 int64_t *pnTime)
3643{
3644 QCBORItem Item;
3645 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3646 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3647}
3648
3649
3650
3651
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003652void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3653 TagSpecification TagSpec,
3654 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003655{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003656 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003657 // Already in error state, do nothing
3658 return;
3659 }
3660
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003661 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003662 QCBORItem Item;
3663
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003664 uError = QCBORDecode_GetNext(pMe, &Item);
3665 if(uError != QCBOR_SUCCESS) {
3666 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003667 return;
3668 }
3669
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003670 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003671
3672 if(pMe->uLastError == QCBOR_SUCCESS) {
3673 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003674 } else {
3675 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003676 }
3677}
3678
Laurence Lundbladec4537442020-04-14 18:53:22 -07003679
3680
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003681
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003682static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003683 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003684 UsefulBufC *pValue,
3685 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003686{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003687 const TagSpecification TagSpec =
3688 {
3689 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003690 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3691 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003692 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003693
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003694 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003695 if(uErr != QCBOR_SUCCESS) {
3696 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003697 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003698
3699 *pValue = pItem->val.string;
3700
3701 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3702 *pbIsNegative = false;
3703 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3704 *pbIsNegative = true;
3705 }
3706
3707 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003708}
3709
3710
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003711/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003712 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003713 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003714void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3715 uint8_t uTagRequirement,
3716 UsefulBufC *pValue,
3717 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003718{
3719 if(pMe->uLastError != QCBOR_SUCCESS) {
3720 // Already in error state, do nothing
3721 return;
3722 }
3723
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003724 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3726 if(uError != QCBOR_SUCCESS) {
3727 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003728 return;
3729 }
3730
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003731 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003732}
3733
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003734
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003735/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003736 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003737*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003738void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3739 int64_t nLabel,
3740 uint8_t uTagRequirement,
3741 UsefulBufC *pValue,
3742 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003743{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003744 QCBORItem Item;
3745 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003746 if(pMe->uLastError != QCBOR_SUCCESS) {
3747 return;
3748 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003749
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003750 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003751}
3752
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003753
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003754/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003755 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003756*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003757void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3758 const char *szLabel,
3759 uint8_t uTagRequirement,
3760 UsefulBufC *pValue,
3761 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003762{
3763 QCBORItem Item;
3764 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003765 if(pMe->uLastError != QCBOR_SUCCESS) {
3766 return;
3767 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003768
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003769 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003770}
3771
3772
3773
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003774
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003775// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003776QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3777 const QCBORItem *pItem,
3778 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003779 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003780{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003781 const TagSpecification TagSpecText =
3782 {
3783 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003784 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3785 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003786 };
3787 const TagSpecification TagSpecBinary =
3788 {
3789 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003790 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3791 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003792 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003793
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003794 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003795
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003796 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003797 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003798 if(pbIsTag257 != NULL) {
3799 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003800 }
3801 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003802 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003803 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003804 if(pbIsTag257 != NULL) {
3805 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003806 }
3807 uReturn = QCBOR_SUCCESS;
3808
3809 } else {
3810 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3811 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003812
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003813 return uReturn;
3814}
3815
Laurence Lundblade93d89472020-10-03 22:30:50 -07003816// Improvement: add methods for wrapped CBOR, a simple alternate
3817// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003818
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003819
3820
3821
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003822#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003823
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003824typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003825
3826
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003827// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003828static QCBORError
3829Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003830{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003831 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003832
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003833 if(uResult != 0) {
3834 /* This loop will run a maximum of 19 times because
3835 * UINT64_MAX < 10 ^^ 19. More than that will cause
3836 * exit with the overflow error
3837 */
3838 for(; nExponent > 0; nExponent--) {
3839 if(uResult > UINT64_MAX / 10) {
3840 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3841 }
3842 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003843 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003844
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003845 for(; nExponent < 0; nExponent++) {
3846 uResult = uResult / 10;
3847 if(uResult == 0) {
3848 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3849 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003850 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003851 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003852 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003853
3854 *puResult = uResult;
3855
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003856 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003857}
3858
3859
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003860// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003861static QCBORError
3862Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003863{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003864 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003866 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003867
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003869 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003870 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003871 */
3872 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003873 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003874 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003875 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003876 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003877 nExponent--;
3878 }
3879
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003880 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003881 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003882 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3883 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003884 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003885 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003886 }
3887
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003888 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003889
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003890 return QCBOR_SUCCESS;
3891}
3892
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003893
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003894/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003895 Compute value with signed mantissa and signed result. Works with
3896 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003897 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003898static inline QCBORError ExponentiateNN(int64_t nMantissa,
3899 int64_t nExponent,
3900 int64_t *pnResult,
3901 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003902{
3903 uint64_t uResult;
3904
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003905 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003906 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003907 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3908
3909 // Do the exponentiation of the positive mantissa
3910 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3911 if(uReturn) {
3912 return uReturn;
3913 }
3914
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003915
Laurence Lundblade983500d2020-05-14 11:49:34 -07003916 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3917 of INT64_MIN. This assumes two's compliment representation where
3918 INT64_MIN is one increment farther from 0 than INT64_MAX.
3919 Trying to write -INT64_MIN doesn't work to get this because the
3920 compiler tries to work with an int64_t which can't represent
3921 -INT64_MIN.
3922 */
3923 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3924
3925 // Error out if too large
3926 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003927 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3928 }
3929
3930 // Casts are safe because of checks above
3931 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3932
3933 return QCBOR_SUCCESS;
3934}
3935
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003936
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003937/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003938 Compute value with signed mantissa and unsigned result. Works with
3939 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003940 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003941static inline QCBORError ExponentitateNU(int64_t nMantissa,
3942 int64_t nExponent,
3943 uint64_t *puResult,
3944 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003945{
3946 if(nMantissa < 0) {
3947 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3948 }
3949
3950 // Cast to unsigned is OK because of check for negative
3951 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3952 // Exponentiation is straight forward
3953 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3954}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003955
3956
3957/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003958 Compute value with signed mantissa and unsigned result. Works with
3959 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003960 */
3961static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3962 int64_t nExponent,
3963 uint64_t *puResult,
3964 fExponentiator pfExp)
3965{
3966 return (*pfExp)(uMantissa, nExponent, puResult);
3967}
3968
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003969#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3970
3971
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003972
3973
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003974
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003975static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003976{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003977 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003978
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003979 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003980 const uint8_t *pByte = BigNum.ptr;
3981 size_t uLen = BigNum.len;
3982 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003983 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003984 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003985 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003986 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003987 }
3988
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003989 *pResult = uResult;
3990 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991}
3992
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003993
Laurence Lundblade887add82020-05-17 05:50:34 -07003994static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003995{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003996 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003997}
3998
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003999
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004000static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001{
4002 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004003 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4004 if(uError) {
4005 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004006 }
4007 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4008 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004009 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004010}
4011
4012
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004013static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004014{
4015 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004016 /* The negative integer furthest from zero for a C int64_t is
4017 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4018 negative number in CBOR is computed as -n - 1 where n is the
4019 encoded integer, where n is what is in the variable BigNum. When
4020 converting BigNum to a uint64_t, the maximum value is thus
4021 INT64_MAX, so that when it -n - 1 is applied to it the result will
4022 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004023
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004024 -n - 1 <= INT64_MIN.
4025 -n - 1 <= -INT64_MAX - 1
4026 n <= INT64_MAX.
4027 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004028 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004029 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004030 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004031 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004032
4033 /// Now apply -n - 1. The cast is safe because
4034 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4035 // is the largest positive integer that an int64_t can
4036 // represent. */
4037 *pnResult = -(int64_t)uResult - 1;
4038
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004039 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004040}
4041
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004042
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004043
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004044
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004045
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004046/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004047Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004048
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004049\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004050
Laurence Lundblade93d89472020-10-03 22:30:50 -07004051\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4052 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004053
4054\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4055
Laurence Lundblade93d89472020-10-03 22:30:50 -07004056\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4057 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004058*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004059static QCBORError
4060ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004061{
4062 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004063 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004064 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004065#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004066 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004067 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4068 http://www.cplusplus.com/reference/cmath/llround/
4069 */
4070 // Not interested in FE_INEXACT
4071 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004072 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4073 *pnValue = llround(pItem->val.dfnum);
4074 } else {
4075 *pnValue = lroundf(pItem->val.fnum);
4076 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004077 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4078 // llround() shouldn't result in divide by zero, but catch
4079 // it here in case it unexpectedly does. Don't try to
4080 // distinguish between the various exceptions because it seems
4081 // they vary by CPU, compiler and OS.
4082 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004083 }
4084 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004085 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004086 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004087#else
4088 return QCBOR_ERR_HW_FLOAT_DISABLED;
4089#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090 break;
4091
4092 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004093 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094 *pnValue = pItem->val.int64;
4095 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004096 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004097 }
4098 break;
4099
4100 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004101 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004102 if(pItem->val.uint64 < INT64_MAX) {
4103 *pnValue = pItem->val.int64;
4104 } else {
4105 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4106 }
4107 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004108 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004109 }
4110 break;
4111
4112 default:
4113 return QCBOR_ERR_UNEXPECTED_TYPE;
4114 }
4115 return QCBOR_SUCCESS;
4116}
4117
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004119void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004120 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004122 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004123{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004124 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004125 return;
4126 }
4127
Laurence Lundbladee6430642020-03-14 21:15:44 -07004128 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004129 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4130 if(uError) {
4131 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004132 return;
4133 }
4134
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004135 if(pItem) {
4136 *pItem = Item;
4137 }
4138
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004139 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140}
4141
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004142
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004143void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4144 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004145 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004146 int64_t *pnValue,
4147 QCBORItem *pItem)
4148{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004149 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004150 if(pMe->uLastError != QCBOR_SUCCESS) {
4151 return;
4152 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004153
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004155}
4156
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004157
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4159 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004161 int64_t *pnValue,
4162 QCBORItem *pItem)
4163{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004164 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004165 if(pMe->uLastError != QCBOR_SUCCESS) {
4166 return;
4167 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004169 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004170}
4171
4172
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004173/*
4174 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004175
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177
Laurence Lundblade93d89472020-10-03 22:30:50 -07004178 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4179 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004180
4181 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4182
Laurence Lundblade93d89472020-10-03 22:30:50 -07004183 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4184 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004185 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004186static QCBORError
4187Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004188{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004189 switch(pItem->uDataType) {
4190
4191 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004193 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004194 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004195 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004196 }
4197 break;
4198
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004199 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004202 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004203 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004204 }
4205 break;
4206
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004207#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4208 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004209 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004210 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004211 pItem->val.expAndMantissa.nExponent,
4212 pnValue,
4213 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004214 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004216 }
4217 break;
4218
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004219 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004221 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004222 pItem->val.expAndMantissa.nExponent,
4223 pnValue,
4224 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004227 }
4228 break;
4229
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004230 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004231 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004232 int64_t nMantissa;
4233 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4235 if(uErr) {
4236 return uErr;
4237 }
4238 return ExponentiateNN(nMantissa,
4239 pItem->val.expAndMantissa.nExponent,
4240 pnValue,
4241 Exponentitate10);
4242 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244 }
4245 break;
4246
4247 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004248 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004249 int64_t nMantissa;
4250 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004251 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4252 if(uErr) {
4253 return uErr;
4254 }
4255 return ExponentiateNN(nMantissa,
4256 pItem->val.expAndMantissa.nExponent,
4257 pnValue,
4258 Exponentitate10);
4259 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004260 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261 }
4262 break;
4263
4264 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004265 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004266 int64_t nMantissa;
4267 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004268 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4269 if(uErr) {
4270 return uErr;
4271 }
4272 return ExponentiateNN(nMantissa,
4273 pItem->val.expAndMantissa.nExponent,
4274 pnValue,
4275 Exponentitate2);
4276 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004277 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004278 }
4279 break;
4280
4281 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004282 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004283 int64_t nMantissa;
4284 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004285 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4286 if(uErr) {
4287 return uErr;
4288 }
4289 return ExponentiateNN(nMantissa,
4290 pItem->val.expAndMantissa.nExponent,
4291 pnValue,
4292 Exponentitate2);
4293 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004294 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004295 }
4296 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004297#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4298
Laurence Lundbladee6430642020-03-14 21:15:44 -07004299
Laurence Lundbladec4537442020-04-14 18:53:22 -07004300 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004301 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004302}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004303
4304
Laurence Lundbladec4537442020-04-14 18:53:22 -07004305/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004306 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004307 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004308void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004309{
4310 QCBORItem Item;
4311
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004312 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004313
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004314 if(pMe->uLastError == QCBOR_SUCCESS) {
4315 // The above conversion succeeded
4316 return;
4317 }
4318
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004319 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004320 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004321 return;
4322 }
4323
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004324 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004325}
4326
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004327
4328/*
4329Public function, see header qcbor/qcbor_decode.h file
4330*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004331void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4332 int64_t nLabel,
4333 uint32_t uConvertTypes,
4334 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004335{
4336 QCBORItem Item;
4337
Laurence Lundblade93d89472020-10-03 22:30:50 -07004338 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4339 nLabel,
4340 uConvertTypes,
4341 pnValue,
4342 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004343
4344 if(pMe->uLastError == QCBOR_SUCCESS) {
4345 // The above conversion succeeded
4346 return;
4347 }
4348
4349 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4350 // The above conversion failed in a way that code below can't correct
4351 return;
4352 }
4353
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004354 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004355}
4356
4357
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004358/*
4359Public function, see header qcbor/qcbor_decode.h file
4360*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004361void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4362 const char *szLabel,
4363 uint32_t uConvertTypes,
4364 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004365{
4366 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004367 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4368 szLabel,
4369 uConvertTypes,
4370 pnValue,
4371 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004372
4373 if(pMe->uLastError == QCBOR_SUCCESS) {
4374 // The above conversion succeeded
4375 return;
4376 }
4377
4378 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4379 // The above conversion failed in a way that code below can't correct
4380 return;
4381 }
4382
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004383 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004384}
4385
4386
Laurence Lundblade93d89472020-10-03 22:30:50 -07004387static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004388{
4389 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004390 case QCBOR_TYPE_DOUBLE:
4391 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004392#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004393 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004394 // Can't use llround here because it will not convert values
4395 // greater than INT64_MAX and less than UINT64_MAX that
4396 // need to be converted so it is more complicated.
4397 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4398 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4399 if(isnan(pItem->val.dfnum)) {
4400 return QCBOR_ERR_FLOAT_EXCEPTION;
4401 } else if(pItem->val.dfnum < 0) {
4402 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4403 } else {
4404 double dRounded = round(pItem->val.dfnum);
4405 // See discussion in DecodeDateEpoch() for
4406 // explanation of - 0x7ff
4407 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4408 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4409 }
4410 *puValue = (uint64_t)dRounded;
4411 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004412 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004413 if(isnan(pItem->val.fnum)) {
4414 return QCBOR_ERR_FLOAT_EXCEPTION;
4415 } else if(pItem->val.fnum < 0) {
4416 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4417 } else {
4418 float fRounded = roundf(pItem->val.fnum);
4419 // See discussion in DecodeDateEpoch() for
4420 // explanation of - 0x7ff
4421 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4422 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4423 }
4424 *puValue = (uint64_t)fRounded;
4425 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004426 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004427 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4428 // round() and roundf() shouldn't result in exceptions here, but
4429 // catch them to be robust and thorough. Don't try to
4430 // distinguish between the various exceptions because it seems
4431 // they vary by CPU, compiler and OS.
4432 return QCBOR_ERR_FLOAT_EXCEPTION;
4433 }
4434
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004435 } else {
4436 return QCBOR_ERR_UNEXPECTED_TYPE;
4437 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004438#else
4439 return QCBOR_ERR_HW_FLOAT_DISABLED;
4440#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004441 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004442
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004443 case QCBOR_TYPE_INT64:
4444 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4445 if(pItem->val.int64 >= 0) {
4446 *puValue = (uint64_t)pItem->val.int64;
4447 } else {
4448 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4449 }
4450 } else {
4451 return QCBOR_ERR_UNEXPECTED_TYPE;
4452 }
4453 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004455 case QCBOR_TYPE_UINT64:
4456 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4457 *puValue = pItem->val.uint64;
4458 } else {
4459 return QCBOR_ERR_UNEXPECTED_TYPE;
4460 }
4461 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004463 default:
4464 return QCBOR_ERR_UNEXPECTED_TYPE;
4465 }
4466
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 return QCBOR_SUCCESS;
4468}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004469
4470
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004471void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004474 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004475{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004476 if(pMe->uLastError != QCBOR_SUCCESS) {
4477 return;
4478 }
4479
Laurence Lundbladec4537442020-04-14 18:53:22 -07004480 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004481
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004482 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4483 if(uError) {
4484 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004485 return;
4486 }
4487
Laurence Lundbladea826c502020-05-10 21:07:00 -07004488 if(pItem) {
4489 *pItem = Item;
4490 }
4491
Laurence Lundblade93d89472020-10-03 22:30:50 -07004492 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004493}
4494
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004495
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004496void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 uint64_t *puValue,
4500 QCBORItem *pItem)
4501{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004502 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004503 if(pMe->uLastError != QCBOR_SUCCESS) {
4504 return;
4505 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506
Laurence Lundblade93d89472020-10-03 22:30:50 -07004507 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004508}
4509
4510
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004511void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004513 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004514 uint64_t *puValue,
4515 QCBORItem *pItem)
4516{
4517 if(pMe->uLastError != QCBOR_SUCCESS) {
4518 return;
4519 }
4520
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004521 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004522 if(pMe->uLastError != QCBOR_SUCCESS) {
4523 return;
4524 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004525
Laurence Lundblade93d89472020-10-03 22:30:50 -07004526 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004527}
4528
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004530
Laurence Lundblade93d89472020-10-03 22:30:50 -07004531static QCBORError
4532UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004533{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 switch(pItem->uDataType) {
4535
4536 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004537 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004538 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4539 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004540 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004541 }
4542 break;
4543
4544 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004545 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4547 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004548 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004549 }
4550 break;
4551
4552#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4553
4554 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004557 pItem->val.expAndMantissa.nExponent,
4558 puValue,
4559 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004560 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004561 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004562 }
4563 break;
4564
4565 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004566 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4568 pItem->val.expAndMantissa.nExponent,
4569 puValue,
4570 Exponentitate2);
4571 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004572 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004573 }
4574 break;
4575
4576 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004577 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004578 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004579 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004580 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581 if(uErr != QCBOR_SUCCESS) {
4582 return uErr;
4583 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004584 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004585 pItem->val.expAndMantissa.nExponent,
4586 puValue,
4587 Exponentitate10);
4588 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004589 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004590 }
4591 break;
4592
4593 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004594 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4596 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004597 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 }
4599 break;
4600
4601 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004603 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004604 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004605 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004606 if(uErr != QCBOR_SUCCESS) {
4607 return uErr;
4608 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004609 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004610 pItem->val.expAndMantissa.nExponent,
4611 puValue,
4612 Exponentitate2);
4613 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004614 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615 }
4616 break;
4617
4618 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004619 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4621 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004622 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004623 }
4624 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004625#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004626 default:
4627 return QCBOR_ERR_UNEXPECTED_TYPE;
4628 }
4629}
4630
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004631
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004632/*
4633 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004634 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004635void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004636{
4637 QCBORItem Item;
4638
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004639 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004640
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004641 if(pMe->uLastError == QCBOR_SUCCESS) {
4642 // The above conversion succeeded
4643 return;
4644 }
4645
4646 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4647 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004648 return;
4649 }
4650
Laurence Lundblade93d89472020-10-03 22:30:50 -07004651 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004652}
4653
Laurence Lundbladec4537442020-04-14 18:53:22 -07004654
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004655/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004656 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004658void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004659 int64_t nLabel,
4660 uint32_t uConvertTypes,
4661 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004662{
4663 QCBORItem Item;
4664
Laurence Lundblade93d89472020-10-03 22:30:50 -07004665 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4666 nLabel,
4667 uConvertTypes,
4668 puValue,
4669 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670
4671 if(pMe->uLastError == QCBOR_SUCCESS) {
4672 // The above conversion succeeded
4673 return;
4674 }
4675
4676 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4677 // The above conversion failed in a way that code below can't correct
4678 return;
4679 }
4680
Laurence Lundblade93d89472020-10-03 22:30:50 -07004681 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004682}
4683
4684
4685/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004686 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004687*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004688void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004689 const char *szLabel,
4690 uint32_t uConvertTypes,
4691 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692{
4693 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004694 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4695 szLabel,
4696 uConvertTypes,
4697 puValue,
4698 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699
4700 if(pMe->uLastError == QCBOR_SUCCESS) {
4701 // The above conversion succeeded
4702 return;
4703 }
4704
4705 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4706 // The above conversion failed in a way that code below can't correct
4707 return;
4708 }
4709
Laurence Lundblade93d89472020-10-03 22:30:50 -07004710 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711}
4712
4713
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004714
4715
Laurence Lundblade9b334962020-08-27 10:55:53 -07004716static QCBORError ConvertDouble(const QCBORItem *pItem,
4717 uint32_t uConvertTypes,
4718 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004719{
4720 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004721 case QCBOR_TYPE_FLOAT:
4722#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4723 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4724 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004725 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004726 *pdValue = (double)pItem->val.fnum;
4727 } else {
4728 return QCBOR_ERR_UNEXPECTED_TYPE;
4729 }
4730 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004731#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004732 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004733#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004734 break;
4735
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004736 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4738 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004739 *pdValue = pItem->val.dfnum;
4740 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004742 }
4743 }
4744 break;
4745
4746 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004747#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004748 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004749 // A simple cast seems to do the job with no worry of exceptions.
4750 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751 *pdValue = (double)pItem->val.int64;
4752
4753 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004754 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004755 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004756#else
4757 return QCBOR_ERR_HW_FLOAT_DISABLED;
4758#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004759 break;
4760
4761 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004762#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004763 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004764 // A simple cast seems to do the job with no worry of exceptions.
4765 // There will be precision loss for some values.
4766 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004767 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004768 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769 }
4770 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004771#else
4772 return QCBOR_ERR_HW_FLOAT_DISABLED;
4773#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774
4775 default:
4776 return QCBOR_ERR_UNEXPECTED_TYPE;
4777 }
4778
4779 return QCBOR_SUCCESS;
4780}
4781
4782
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004783void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004784 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004786 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004787{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004788 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004789 return;
4790 }
4791
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004792 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004793
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004794 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004795 if(uError) {
4796 pMe->uLastError = (uint8_t)uError;
4797 return;
4798 }
4799
4800 if(pItem) {
4801 *pItem = Item;
4802 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004803
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004805}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004806
Laurence Lundbladec4537442020-04-14 18:53:22 -07004807
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4809 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004810 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004811 double *pdValue,
4812 QCBORItem *pItem)
4813{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004814 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004815 if(pMe->uLastError != QCBOR_SUCCESS) {
4816 return;
4817 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004819 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820}
4821
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004822
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4824 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004825 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 double *pdValue,
4827 QCBORItem *pItem)
4828{
4829 if(pMe->uLastError != QCBOR_SUCCESS) {
4830 return;
4831 }
4832
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004833 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004834 if(pMe->uLastError != QCBOR_SUCCESS) {
4835 return;
4836 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004838 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839}
4840
4841
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004842#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004843static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4844{
4845 double dResult;
4846
4847 dResult = 0.0;
4848 const uint8_t *pByte = BigNum.ptr;
4849 size_t uLen = BigNum.len;
4850 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004851 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004852 while(uLen--) {
4853 dResult = (dResult * 256.0) + (double)*pByte++;
4854 }
4855
4856 return dResult;
4857}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004858#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4859
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004860
Laurence Lundblade93d89472020-10-03 22:30:50 -07004861static QCBORError
4862DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004863{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004864#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004865 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004866 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4867
4868 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004869 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004870
4871#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004873 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004874 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004875 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4876 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4877 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004878 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879 }
4880 break;
4881
4882 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004883 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004884 // Underflow gives 0, overflow gives infinity
4885 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4886 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004887 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004888 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889 }
4890 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004891#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004892
4893 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4896 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004897 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004898 }
4899 break;
4900
4901 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004902 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004903 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004904 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906 }
4907 break;
4908
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004909#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004910 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004911 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4913 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4914 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004915 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004916 }
4917 break;
4918
4919 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004920 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4922 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4923 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004924 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004925 }
4926 break;
4927
4928 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004929 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4931 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4932 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004933 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004934 }
4935 break;
4936
4937 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004938 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004939 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004940 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4941 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004942 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004943 }
4944 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004945#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4946
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004947 default:
4948 return QCBOR_ERR_UNEXPECTED_TYPE;
4949 }
4950
4951 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004952
4953#else
4954 (void)pItem;
4955 (void)uConvertTypes;
4956 (void)pdValue;
4957 return QCBOR_ERR_HW_FLOAT_DISABLED;
4958#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4959
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960}
4961
4962
4963/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004964 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004965*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004966void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4967 uint32_t uConvertTypes,
4968 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004969{
4970
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004971 QCBORItem Item;
4972
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004973 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004974
4975 if(pMe->uLastError == QCBOR_SUCCESS) {
4976 // The above conversion succeeded
4977 return;
4978 }
4979
4980 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4981 // The above conversion failed in a way that code below can't correct
4982 return;
4983 }
4984
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004985 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004986}
4987
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004988
4989/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004990 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004991*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004992void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4993 int64_t nLabel,
4994 uint32_t uConvertTypes,
4995 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004996{
4997 QCBORItem Item;
4998
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004999 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005000
5001 if(pMe->uLastError == QCBOR_SUCCESS) {
5002 // The above conversion succeeded
5003 return;
5004 }
5005
5006 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5007 // The above conversion failed in a way that code below can't correct
5008 return;
5009 }
5010
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005011 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005012}
5013
5014
5015/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005016 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005017*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005018void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5019 const char *szLabel,
5020 uint32_t uConvertTypes,
5021 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005022{
5023 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005024 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005025
5026 if(pMe->uLastError == QCBOR_SUCCESS) {
5027 // The above conversion succeeded
5028 return;
5029 }
5030
5031 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5032 // The above conversion failed in a way that code below can't correct
5033 return;
5034 }
5035
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005036 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005037}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005038
5039
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005040
5041
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005042#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005043static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5044{
5045 while((uInt & 0xff00000000000000UL) == 0) {
5046 uInt = uInt << 8;
5047 };
5048
5049 UsefulOutBuf UOB;
5050
5051 UsefulOutBuf_Init(&UOB, Buffer);
5052
5053 while(uInt) {
5054 const uint64_t xx = uInt & 0xff00000000000000UL;
5055 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5056 uInt = uInt << 8;
5057 (void)xx;
5058 }
5059
5060 return UsefulOutBuf_OutUBuf(&UOB);
5061}
5062
5063
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005064static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5065 TagSpecification TagSpec,
5066 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005067{
5068 QCBORError uErr;
5069 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005070 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005071 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005072 if(uErr != QCBOR_SUCCESS) {
5073 goto Done;
5074 }
5075
5076 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5077 break; // Successful exit. Moving on to finish decoding.
5078 }
5079
5080 // The item is an array, which means an undecoded
5081 // mantissa and exponent, so decode it. It will then
5082 // have a different type and exit the loop if.
5083 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5084 if(uErr != QCBOR_SUCCESS) {
5085 goto Done;
5086 }
5087
5088 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005089 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005090 }
5091Done:
5092 return uErr;
5093}
5094
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005095
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005096static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005097 TagSpecification TagSpec,
5098 QCBORItem *pItem,
5099 int64_t *pnMantissa,
5100 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005101{
5102 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005103
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005104 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005105 if(uErr != QCBOR_SUCCESS) {
5106 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005107 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005108
Laurence Lundblade9b334962020-08-27 10:55:53 -07005109 switch (pItem->uDataType) {
5110
5111 case QCBOR_TYPE_DECIMAL_FRACTION:
5112 case QCBOR_TYPE_BIGFLOAT:
5113 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5114 *pnExponent = pItem->val.expAndMantissa.nExponent;
5115 break;
5116
5117 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5118 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5119 *pnExponent = pItem->val.expAndMantissa.nExponent;
5120 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5121 break;
5122
5123 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5124 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5125 *pnExponent = pItem->val.expAndMantissa.nExponent;
5126 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5127 break;
5128
5129 default:
5130 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5131 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005132
5133 Done:
5134 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005135}
5136
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005137
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005138static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005139 TagSpecification TagSpec,
5140 QCBORItem *pItem,
5141 UsefulBuf BufferForMantissa,
5142 UsefulBufC *pMantissa,
5143 bool *pbIsNegative,
5144 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005145{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005146 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005147
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005148 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005149 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005150 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005151 }
5152
5153 uint64_t uMantissa;
5154
5155 switch (pItem->uDataType) {
5156
5157 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005158 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005159 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5160 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5161 *pbIsNegative = false;
5162 } else {
5163 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5164 *pbIsNegative = true;
5165 }
5166 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5167 *pnExponent = pItem->val.expAndMantissa.nExponent;
5168 break;
5169
5170 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005171 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005172 *pnExponent = pItem->val.expAndMantissa.nExponent;
5173 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5174 *pbIsNegative = false;
5175 break;
5176
5177 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005178 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005179 *pnExponent = pItem->val.expAndMantissa.nExponent;
5180 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5181 *pbIsNegative = true;
5182 break;
5183
5184 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005185 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005186 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005187
5188Done:
5189 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005190}
5191
5192
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005193/*
5194 Public function, see header qcbor/qcbor_decode.h file
5195*/
5196void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5197 uint8_t uTagRequirement,
5198 int64_t *pnMantissa,
5199 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005200{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005201 if(pMe->uLastError != QCBOR_SUCCESS) {
5202 return;
5203 }
5204
5205 QCBORItem Item;
5206 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5207 if(uError) {
5208 pMe->uLastError = (uint8_t)uError;
5209 return;
5210 }
5211
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005212 const TagSpecification TagSpec =
5213 {
5214 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005215 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5216 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5217 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005218 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005219
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005220 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005221}
5222
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005223
5224/*
5225 Public function, see header qcbor/qcbor_decode.h file
5226*/
5227void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005228 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005229 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230 int64_t *pnMantissa,
5231 int64_t *pnExponent)
5232{
5233 if(pMe->uLastError != QCBOR_SUCCESS) {
5234 return;
5235 }
5236
5237 QCBORItem Item;
5238 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5239
5240 const TagSpecification TagSpec =
5241 {
5242 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005243 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5244 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5245 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005246 };
5247
5248 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5249}
5250
5251
5252/*
5253 Public function, see header qcbor/qcbor_decode.h file
5254*/
5255void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005256 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005257 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005258 int64_t *pnMantissa,
5259 int64_t *pnExponent)
5260{
5261 if(pMe->uLastError != QCBOR_SUCCESS) {
5262 return;
5263 }
5264
5265 QCBORItem Item;
5266 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5267
5268 const TagSpecification TagSpec =
5269 {
5270 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005271 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5272 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5273 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005274 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005275
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005276 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5277}
5278
5279
5280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
5283void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5284 uint8_t uTagRequirement,
5285 UsefulBuf MantissaBuffer,
5286 UsefulBufC *pMantissa,
5287 bool *pbMantissaIsNegative,
5288 int64_t *pnExponent)
5289{
5290 if(pMe->uLastError != QCBOR_SUCCESS) {
5291 return;
5292 }
5293
5294 QCBORItem Item;
5295 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5296 if(uError) {
5297 pMe->uLastError = (uint8_t)uError;
5298 return;
5299 }
5300
5301 const TagSpecification TagSpec =
5302 {
5303 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005304 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5305 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5306 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 };
5308
Laurence Lundblade93d89472020-10-03 22:30:50 -07005309 ProcessMantissaAndExponentBig(pMe,
5310 TagSpec,
5311 &Item,
5312 MantissaBuffer,
5313 pMantissa,
5314 pbMantissaIsNegative,
5315 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005316}
5317
5318
5319/*
5320 Public function, see header qcbor/qcbor_decode.h file
5321*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005322void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005323 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005324 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005325 UsefulBuf BufferForMantissa,
5326 UsefulBufC *pMantissa,
5327 bool *pbIsNegative,
5328 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005329{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005330 if(pMe->uLastError != QCBOR_SUCCESS) {
5331 return;
5332 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005333
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005334 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005335 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005340 const TagSpecification TagSpec =
5341 {
5342 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005343 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5344 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5345 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005346 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005347
Laurence Lundblade93d89472020-10-03 22:30:50 -07005348 ProcessMantissaAndExponentBig(pMe,
5349 TagSpec,
5350 &Item,
5351 BufferForMantissa,
5352 pMantissa,
5353 pbIsNegative,
5354 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005355}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005356
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005357
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005358/*
5359 Public function, see header qcbor/qcbor_decode.h file
5360*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005361void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005362 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005363 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005364 UsefulBuf BufferForMantissa,
5365 UsefulBufC *pMantissa,
5366 bool *pbIsNegative,
5367 int64_t *pnExponent)
5368{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005369 if(pMe->uLastError != QCBOR_SUCCESS) {
5370 return;
5371 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005372
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005373 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005374 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5375 if(pMe->uLastError != QCBOR_SUCCESS) {
5376 return;
5377 }
5378
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005379 const TagSpecification TagSpec =
5380 {
5381 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005382 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5383 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5384 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005385 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005386
5387 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5388}
5389
5390
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005391/*
5392 Public function, see header qcbor/qcbor_decode.h file
5393*/
5394void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5395 uint8_t uTagRequirement,
5396 int64_t *pnMantissa,
5397 int64_t *pnExponent)
5398{
5399 if(pMe->uLastError != QCBOR_SUCCESS) {
5400 return;
5401 }
5402
5403 QCBORItem Item;
5404 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5405 if(uError) {
5406 pMe->uLastError = (uint8_t)uError;
5407 return;
5408 }
5409 const TagSpecification TagSpec =
5410 {
5411 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005412 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5413 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5414 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415 };
5416
5417 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5418}
5419
5420
5421/*
5422 Public function, see header qcbor/qcbor_decode.h file
5423*/
5424void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005425 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005426 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005427 int64_t *pnMantissa,
5428 int64_t *pnExponent)
5429{
5430 if(pMe->uLastError != QCBOR_SUCCESS) {
5431 return;
5432 }
5433
5434 QCBORItem Item;
5435 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5436 if(pMe->uLastError != QCBOR_SUCCESS) {
5437 return;
5438 }
5439
5440 const TagSpecification TagSpec =
5441 {
5442 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005443 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5444 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5445 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005446 };
5447
5448 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5449}
5450
5451
5452/*
5453 Public function, see header qcbor/qcbor_decode.h file
5454*/
5455void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005456 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005457 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005458 int64_t *pnMantissa,
5459 int64_t *pnExponent)
5460{
5461 if(pMe->uLastError != QCBOR_SUCCESS) {
5462 return;
5463 }
5464
5465 QCBORItem Item;
5466 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5467 if(pMe->uLastError != QCBOR_SUCCESS) {
5468 return;
5469 }
5470
5471 const TagSpecification TagSpec =
5472 {
5473 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005474 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5475 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5476 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477 };
5478
5479 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5480}
5481
5482
5483/*
5484 Public function, see header qcbor/qcbor_decode.h file
5485*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005486void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5487 uint8_t uTagRequirement,
5488 UsefulBuf MantissaBuffer,
5489 UsefulBufC *pMantissa,
5490 bool *pbMantissaIsNegative,
5491 int64_t *pnExponent)
5492{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005493 if(pMe->uLastError != QCBOR_SUCCESS) {
5494 return;
5495 }
5496
5497 QCBORItem Item;
5498 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5499 if(uError) {
5500 pMe->uLastError = (uint8_t)uError;
5501 return;
5502 }
5503
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 const TagSpecification TagSpec =
5505 {
5506 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005507 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5508 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5509 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005510 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005511
5512 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005513}
5514
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005515
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005516/*
5517 Public function, see header qcbor/qcbor_decode.h file
5518*/
5519void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005521 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005522 UsefulBuf BufferForMantissa,
5523 UsefulBufC *pMantissa,
5524 bool *pbIsNegative,
5525 int64_t *pnExponent)
5526{
5527 if(pMe->uLastError != QCBOR_SUCCESS) {
5528 return;
5529 }
5530
5531 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005532 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5533 if(pMe->uLastError != QCBOR_SUCCESS) {
5534 return;
5535 }
5536
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005537 const TagSpecification TagSpec =
5538 {
5539 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005540 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5541 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5542 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005543 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005544
Laurence Lundblade93d89472020-10-03 22:30:50 -07005545 ProcessMantissaAndExponentBig(pMe,
5546 TagSpec,
5547 &Item,
5548 BufferForMantissa,
5549 pMantissa,
5550 pbIsNegative,
5551 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005552}
5553
5554
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005555/*
5556 Public function, see header qcbor/qcbor_decode.h file
5557*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005558void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005559 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005560 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005561 UsefulBuf BufferForMantissa,
5562 UsefulBufC *pMantissa,
5563 bool *pbIsNegative,
5564 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005565{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005566 if(pMe->uLastError != QCBOR_SUCCESS) {
5567 return;
5568 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005569
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005570 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005571 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5572 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005573 return;
5574 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005575
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005576 const TagSpecification TagSpec =
5577 {
5578 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005579 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5580 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5581 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005582 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005583
Laurence Lundblade93d89472020-10-03 22:30:50 -07005584 ProcessMantissaAndExponentBig(pMe,
5585 TagSpec,
5586 &Item,
5587 BufferForMantissa,
5588 pMantissa,
5589 pbIsNegative,
5590 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005591}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005592
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005593#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */