blob: 4cb499f8e7b558043a9902ef94ccbca1a039a363 [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
514StringAllocator_Free(const QCORInternalAllocator *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
522StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
523 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
530StringAllocator_Allocate(const QCORInternalAllocator *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
536StringAllocator_Destruct(const QCORInternalAllocator *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
604/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800605 This decodes the fundamental part of a CBOR data item, the type and
606 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800607
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700608 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladeee851742020-01-08 08:37:05 -0800610 This does the network->host byte order conversion. The conversion
611 here also results in the conversion for floats in addition to that
612 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800613
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700614 This returns:
615 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800616
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800617 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800618 tags and floats and length for strings and arrays
619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800621 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800622
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800623 The int type is preferred to uint8_t for some variables as this
624 avoids integer promotions, can reduce code size and makes
625 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700626
627 @retval QCBOR_ERR_UNSUPPORTED
628
629 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700631static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 int *pnMajorType,
633 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800634 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700636 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800637
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800642 const int nTmpMajorType = nInitialByte >> 5;
643 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800644
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800645 // Where the number or argument accumulates
646 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800647
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700649 // Need to get 1,2,4 or 8 additional argument bytes. Map
650 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800651 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800652
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800653 // Loop getting all the bytes in the argument
654 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800655 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800656 // This shift and add gives the endian conversion
657 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
658 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800659 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800660 // The reserved and thus-far unused additional info values
661 nReturn = QCBOR_ERR_UNSUPPORTED;
662 goto Done;
663 } else {
664 // Less than 24, additional info is argument or 31, an indefinite length
665 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 if(UsefulInputBuf_GetError(pUInBuf)) {
670 nReturn = QCBOR_ERR_HIT_END;
671 goto Done;
672 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800673
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674 // All successful if we got here.
675 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800676 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800677 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800678 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680Done:
681 return nReturn;
682}
683
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700685/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686 CBOR doesn't explicitly specify two's compliment for integers but all
687 CPUs use it these days and the test vectors in the RFC are so. All
688 integers in the CBOR structure are positive and the major type
689 indicates positive or negative. CBOR can express positive integers
690 up to 2^x - 1 where x is the number of bits and negative integers
691 down to 2^x. Note that negative numbers can be one more away from
692 zero than positive. Stdint, as far as I can tell, uses two's
693 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800694
Laurence Lundblade9b334962020-08-27 10:55:53 -0700695 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800696 used carefully here, and in particular why it isn't used in the interface.
697 Also see
698 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
699
700 Int is used for values that need less than 16-bits and would be subject
701 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700702
703 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700705static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800706DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700707{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700708 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
711 if (uNumber <= INT64_MAX) {
712 pDecodedItem->val.int64 = (int64_t)uNumber;
713 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 } else {
716 pDecodedItem->val.uint64 = uNumber;
717 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800718
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700719 }
720 } else {
721 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 // CBOR's representation of negative numbers lines up with the
723 // two-compliment representation. A negative integer has one
724 // more in range than a positive integer. INT64_MIN is
725 // equal to (-INT64_MAX) - 1.
726 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 } else {
730 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000731 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 nReturn = QCBOR_ERR_INT_OVERFLOW;
733 }
734 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736 return nReturn;
737}
738
739// Make sure #define value line up as DecodeSimple counts on this.
740#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
741#error QCBOR_TYPE_FALSE macro value wrong
742#endif
743
744#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
745#error QCBOR_TYPE_TRUE macro value wrong
746#endif
747
748#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
749#error QCBOR_TYPE_NULL macro value wrong
750#endif
751
752#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
753#error QCBOR_TYPE_UNDEF macro value wrong
754#endif
755
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700756#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
757#error QCBOR_TYPE_BREAK macro value wrong
758#endif
759
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
761#error QCBOR_TYPE_DOUBLE macro value wrong
762#endif
763
764#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
765#error QCBOR_TYPE_FLOAT macro value wrong
766#endif
767
768/*
769 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700770
771 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
772
773 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700775static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700777{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700778 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700780 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800781 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700782 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
783 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800784 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800785
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800786 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800787 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
788 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700790 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700791#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700792 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700793 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700794 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700795 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
796 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800797#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700798 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800799#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700800 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700801 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700802 // Single precision is normally returned as a double
803 // since double is widely supported, there is no loss of
804 // precision, it makes it easy for the caller in
805 // most cases and it can be converted back to single
806 // with no loss of precision
807 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700808 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700809 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700810 {
811 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
812#ifndef QCBOR_DISABLE_FLOAT_HW_USE
813 // In the normal case, use HW to convert float to double.
814 pDecodedItem->val.dfnum = (double)f;
815 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800816#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700817 // Use of float HW is disabled, return as a float.
818 pDecodedItem->val.fnum = f;
819 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
820
821 // IEEE754_FloatToDouble() could be used here to return
822 // as a double, but it adds object code and most likely
823 // anyone disabling FLOAT HW use doesn't care about
824 // floats and wants to save object code.
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800825#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700826 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700827 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700828
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700829 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700830 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700831 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700832 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834 case CBOR_SIMPLEV_FALSE: // 20
835 case CBOR_SIMPLEV_TRUE: // 21
836 case CBOR_SIMPLEV_NULL: // 22
837 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700838 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841 case CBOR_SIMPLEV_ONEBYTE: // 24
842 if(uNumber <= CBOR_SIMPLE_BREAK) {
843 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700844 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845 goto Done;
846 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800847 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800849
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700850 default: // 0-19
851 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800852 /*
853 DecodeTypeAndNumber will make uNumber equal to
854 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
855 safe because the 2, 4 and 8 byte lengths of uNumber are in
856 the double/float cases above
857 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 pDecodedItem->val.uSimple = (uint8_t)uNumber;
859 break;
860 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700862Done:
863 return nReturn;
864}
865
866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530868 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700869
870 @retval QCBOR_ERR_HIT_END
871
872 @retval QCBOR_ERR_STRING_ALLOCATE
873
874 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700876static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800877 uint64_t uStrLen,
878 UsefulInputBuf *pUInBuf,
879 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700881 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800882
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800883 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
884 // This check makes the casts to size_t below safe.
885
886 // 4 bytes less than the largest sizeof() so this can be tested by
887 // putting a SIZE_MAX length in the CBOR test input (no one will
888 // care the limit on strings is 4 bytes shorter).
889 if(uStrLen > SIZE_MAX-4) {
890 nReturn = QCBOR_ERR_STRING_TOO_LONG;
891 goto Done;
892 }
893
894 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530895 if(UsefulBuf_IsNULLC(Bytes)) {
896 // Failed to get the bytes for this string item
897 nReturn = QCBOR_ERR_HIT_END;
898 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530900
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800901#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800902 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530903 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800904 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530905 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700906 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530907 goto Done;
908 }
909 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800910 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800911 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530912 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800913#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
914 (void)pAllocator;
915#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
916
917 // Normal case with no string allocator
918 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800919
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530920Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700921 return nReturn;
922}
923
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800925/* Map the CBOR major types for strings to the QCBOR types for strngs */
926static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
927{
928 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
929 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
930 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800932 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
933 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
934 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800936 return (uint8_t)(nCBORMajorType + 4);
937}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938
939
Laurence Lundbladeee851742020-01-08 08:37:05 -0800940// Make sure the constants align as this is assumed by
941// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
943#error QCBOR_TYPE_ARRAY value not lined up with major type
944#endif
945#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
946#error QCBOR_TYPE_MAP value not lined up with major type
947#endif
948
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800950 This gets a single data item and decodes it including preceding
951 optional tagging. This does not deal with arrays and maps and nesting
952 except to decode the data item introducing them. Arrays and maps are
953 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800954
Laurence Lundbladeee851742020-01-08 08:37:05 -0800955 Errors detected here include: an array that is too long to decode,
956 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700957
958 @retval QCBOR_ERR_UNSUPPORTED
959
960 @retval QCBOR_ERR_HIT_END
961
962 @retval QCBOR_ERR_INT_OVERFLOW
963
964 @retval QCBOR_ERR_STRING_ALLOCATE
965
966 @retval QCBOR_ERR_STRING_TOO_LONG
967
968 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
969
970 @retval QCBOR_ERR_BAD_TYPE_7
971
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700972 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800973static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
974 QCBORItem *pDecodedItem,
975 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700977 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundbladeee851742020-01-08 08:37:05 -0800979 /*
980 Get the major type and the number. Number could be length of more
981 bytes or the value depending on the major type nAdditionalInfo is
982 an encoding of the length of the uNumber and is needed to decode
983 floats and doubles
984 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100985 int nMajorType = 0;
986 uint64_t uNumber = 0;
987 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700989 memset(pDecodedItem, 0, sizeof(QCBORItem));
990
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800991 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundbladeee851742020-01-08 08:37:05 -0800993 // Error out here if we got into trouble on the type and number. The
994 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700995 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700996 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700997 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundbladeee851742020-01-08 08:37:05 -0800999 // At this point the major type and the value are valid. We've got
1000 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001001 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1003 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001004 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001005 nReturn = QCBOR_ERR_BAD_INT;
1006 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001008 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1012 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001013 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001015 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001017 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 }
1019 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001020
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001021 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1022 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1023 // Record the number of items in the array or map
1024 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001025 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 goto Done;
1027 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001028 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001029#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001030 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001031#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1032 nReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1033 break;
1034#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001036 // type conversion OK because of check above
1037 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001039 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001040 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001041 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001045 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001046 nReturn = QCBOR_ERR_BAD_INT;
1047 } else {
1048 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001049 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001050 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001051 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundbladeee851742020-01-08 08:37:05 -08001053 case CBOR_MAJOR_TYPE_SIMPLE:
1054 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001055 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001056 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001057
Laurence Lundbladeee851742020-01-08 08:37:05 -08001058 default:
1059 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 nReturn = QCBOR_ERR_UNSUPPORTED;
1061 break;
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064Done:
1065 return nReturn;
1066}
1067
1068
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001069/**
1070 * @brief Process indefinite length strings
1071 *
1072 * @param[in] pMe Decoder context
1073 * @param[in,out] pDecodedItem The decoded item that work is done on.
1074 *
1075 * @retval QCBOR_ERR_UNSUPPORTED
1076 * @retval QCBOR_ERR_HIT_END
1077 * @retval QCBOR_ERR_INT_OVERFLOW
1078 * @retval QCBOR_ERR_STRING_ALLOCATE
1079 * @retval QCBOR_ERR_STRING_TOO_LONG
1080 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1081 * @retval QCBOR_ERR_BAD_TYPE_7
1082 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1083 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1084 *
1085 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1086 *
1087 * If it is, this loops getting the subsequent chunks that make up the
1088 * string. The string allocator is used to make a contiguous buffer for
1089 * the chunks. When this completes @c pDecodedItem contains the
1090 * put-together string.
1091 *
1092 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001094static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001095GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001097 /* Aproximate stack usage
1098 * 64-bit 32-bit
1099 * local vars 32 16
1100 * 2 UsefulBufs 32 16
1101 * QCBORItem 56 52
1102 * TOTAL 120 74
1103 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001104
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001105 /* The string allocator is used here for two purposes: 1)
1106 * coalescing the chunks of an indefinite length string, 2)
1107 * allocating storage for every string returned.
1108 *
1109 * The first use is below in this function. Indefinite length
1110 * strings cannot be processed at all without a string allocator.
1111 *
1112 * The second used is in DecodeBytes() which is called by
1113 * GetNext_Item() below. This second use unneccessary for most use
1114 * and only happens when requested in the call to
1115 * QCBORDecode_SetMemPool(). If the second use not requested then
1116 * NULL is passed for the string allocator to GetNext_Item().
1117 *
1118 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1119 * allocator altogether and thus both of these uses. It reduced the
1120 * decoder object code by about 400 bytes.
1121 */
1122 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001123
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001124#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1125 const QCORInternalAllocator *pAllocator = NULL;
1126
1127 if(pMe->StringAllocator.pfAllocator) {
1128 pAllocator = &(pMe->StringAllocator);
1129 if(pMe->bStringAllocateAll) {
1130 pAllocatorForGetNext = pAllocator;
1131 }
1132 }
1133#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1134
1135 QCBORError uReturn;
1136 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1137 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 goto Done;
1139 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001140
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001141 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001142 const uint8_t uStringType = pDecodedItem->uDataType;
1143 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001144 goto Done;
1145 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001146
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001147 /* Is this a string with an indefinite length? */
1148 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1149 goto Done;
1150 }
1151
1152#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1153 /* Can't do indefinite length strings without a string allocator */
1154 if(pAllocator == NULL) {
1155 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1156 goto Done;
1157 }
1158
1159 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001160 UsefulBufC FullString = NULLUsefulBufC;
1161
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001163 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001164 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 /* Pass a NULL string allocator to GetNext_Item() because the
1166 * individual string chunks in an indefinite length should not
1167 * be allocated. They are always copied in the the contiguous
1168 * buffer allocated here.
1169 */
1170 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1171 if(uReturn) {
1172 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001173 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001175 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001176 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001177 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001178 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301179 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001180 break;
1181 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001182
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001183 /* All chunks must be of the same type, the type of the item
1184 * that introduces the indefinite length string. This also
1185 * catches errors where the chunk is not a string at all and an
1186 * indefinite length string inside an indefinite length string.
1187 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001188 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1190 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001191 break;
1192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001194 /* The first time throurgh FullString.ptr is NULL and this is
1195 * equivalent to StringAllocator_Allocate(). Subsequently it is
1196 * not NULL and a reallocation happens.
1197 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001198 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1199 UNCONST_POINTER(FullString.ptr),
1200 FullString.len + StringChunkItem.val.string.len);
1201
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001202 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001203 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001204 break;
1205 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001206
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001207 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001208 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001209 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001211 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1212 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001213 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001214 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001215#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1216 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1217#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001218
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001219Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001220 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001221}
1222
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001223
Laurence Lundblade9b334962020-08-27 10:55:53 -07001224static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001225 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001226 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001227 } else if(uTagVal == CBOR_TAG_INVALID16) {
1228 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001230 // This won't be negative because of code below in GetNext_TaggedItem()
1231 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1232 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001233 }
1234}
1235
Laurence Lundblade9b334962020-08-27 10:55:53 -07001236
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001237/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001238 Gets all optional tag data items preceding a data item that is not an
1239 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240
1241 @retval QCBOR_ERR_UNSUPPORTED
1242
1243 @retval QCBOR_ERR_HIT_END
1244
1245 @retval QCBOR_ERR_INT_OVERFLOW
1246
1247 @retval QCBOR_ERR_STRING_ALLOCATE
1248
1249 @retval QCBOR_ERR_STRING_TOO_LONG
1250
1251 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1252
1253 @retval QCBOR_ERR_BAD_TYPE_7
1254
1255 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1256
1257 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1258
1259 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001260 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001261static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001262GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001263{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001264 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1265 CBOR_TAG_INVALID16,
1266 CBOR_TAG_INVALID16,
1267 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001268
Laurence Lundblade9b334962020-08-27 10:55:53 -07001269 QCBORError uReturn = QCBOR_SUCCESS;
1270
Laurence Lundblade59289e52019-12-30 13:44:37 -08001271 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001272 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001273 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1274 if(uErr != QCBOR_SUCCESS) {
1275 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001276 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001278
Laurence Lundblade9b334962020-08-27 10:55:53 -07001279 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001280 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282 break;
1283 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001284
Laurence Lundblade9b334962020-08-27 10:55:53 -07001285 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1286 // No room in the tag list
1287 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1288 // Continue on to get all tags on this item even though
1289 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001290 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001291 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001292 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001293 // Slide tags over one in the array to make room at index 0
1294 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1295 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001297
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001298 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001299 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001300 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001301 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001303 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001304 break;
1305 }
1306 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1307 break;
1308 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001309 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001310 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1311 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001312 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1313 // Continue on to get all tags on this item even though
1314 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001315 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001316 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001317 }
1318
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001319 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001320 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001321 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001322
1323 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001324 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001325 }
1326 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001328Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001329 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001330}
1331
1332
1333/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001334 This layer takes care of map entries. It combines the label and data
1335 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001336
1337 @retval QCBOR_ERR_UNSUPPORTED
1338
1339 @retval QCBOR_ERR_HIT_END
1340
1341 @retval QCBOR_ERR_INT_OVERFLOW
1342
1343 @retval QCBOR_ERR_STRING_ALLOCATE
1344
1345 @retval QCBOR_ERR_STRING_TOO_LONG
1346
1347 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1348
1349 @retval QCBOR_ERR_BAD_TYPE_7
1350
1351 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1352
1353 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1354
1355 @retval QCBOR_ERR_TOO_MANY_TAGS
1356
1357 @retval QCBOR_ERR_MAP_LABEL_TYPE
1358
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001359 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001360 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001361static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001362GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001363{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001364 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001365 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001366 if(nReturn)
1367 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001368
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001369 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001370 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001371 goto Done;
1372 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001373
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001374 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1375 // In a map and caller wants maps decoded, not treated as arrays
1376
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001377 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001378 // If in a map and the right decoding mode, get the label
1379
Laurence Lundbladeee851742020-01-08 08:37:05 -08001380 // Save label in pDecodedItem and get the next which will
1381 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001382 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001383 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001384 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001385 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001386 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001387
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301388 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001389
1390 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1391 // strings are always good labels
1392 pDecodedItem->label.string = LabelItem.val.string;
1393 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1394 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001395 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001396 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1397 goto Done;
1398 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1399 pDecodedItem->label.int64 = LabelItem.val.int64;
1400 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1401 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1402 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1403 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1404 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1405 pDecodedItem->label.string = LabelItem.val.string;
1406 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1407 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1408 } else {
1409 // label is not an int or a string. It is an arrray
1410 // or a float or such and this implementation doesn't handle that.
1411 // Also, tags on labels are ignored.
1412 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1413 goto Done;
1414 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001415 }
1416 } else {
1417 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001418 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001419 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001420 goto Done;
1421 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001422 // Decoding a map as an array
1423 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001424 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1425 // Cast is needed because of integer promotion
1426 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001427 }
1428 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001429
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001430Done:
1431 return nReturn;
1432}
1433
1434
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001435#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001436/*
1437 See if next item is a CBOR break. If it is, it is consumed,
1438 if not it is not consumed.
1439*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001440static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001441NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1442{
1443 *pbNextIsBreak = false;
1444 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001445 QCBORItem Peek;
1446 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1447 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1448 if(uReturn != QCBOR_SUCCESS) {
1449 return uReturn;
1450 }
1451 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001452 // It is not a break, rewind so it can be processed normally.
1453 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001454 } else {
1455 *pbNextIsBreak = true;
1456 }
1457 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001458
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001459 return QCBOR_SUCCESS;
1460}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001461#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001462
1463
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001464/*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001465 * An item was just consumed, now figure out if it was the
1466 * end of an array/map map that can be closed out. That
1467 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001468*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001469static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001470{
1471 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001472
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001473 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001474 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1475
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001476 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1477 /* Nesting level is bstr-wrapped CBOR */
1478
1479 /* Ascent for bstr-wrapped CBOR is always by explicit call
1480 * so no further ascending can happen.
1481 */
1482 break;
1483
1484 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1485 /* Level is a definite-length array/map */
1486
1487 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001488 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1489 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001490 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001491 break;
1492 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001493 /* All items in a definite length array were consumed so it
1494 * is time to ascend one level. This happens below.
1495 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001496
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001497#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001498 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001499 /* Level is an indefinite-length array/map. */
1500
1501 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001502 bool bIsBreak = false;
1503 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1504 if(uReturn != QCBOR_SUCCESS) {
1505 goto Done;
1506 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001507
1508 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001509 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001510 break;
1511 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001512
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001513 /* It was a break in an indefinite length map / array so
1514 * it is time to ascend one level.
1515 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001516
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001517#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001518 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001519
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001520
1521 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001522
Laurence Lundblade93d89472020-10-03 22:30:50 -07001523 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001524 * QCBORDecode_ExitBoundedMode().
1525 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001526 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001527 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001528 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001529 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001530 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001531 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001532
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001533 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001534 break;
1535 }
1536
1537 /* Finally, actually ascend one level. */
1538 DecodeNesting_Ascend(&(pMe->nesting));
1539 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001540
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001541 uReturn = QCBOR_SUCCESS;
1542
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001543#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001544Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001545#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1546
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001547 return uReturn;
1548}
1549
1550
1551/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001552 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001553 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1554 indefinte length maps and arrays by looking at the item count or
1555 finding CBOR breaks. It detects the ends of the top-level sequence
1556 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001557
1558 @retval QCBOR_ERR_UNSUPPORTED X
1559
1560 @retval QCBOR_ERR_HIT_END
1561
1562 @retval QCBOR_ERR_INT_OVERFLOW X
1563
1564 @retval QCBOR_ERR_STRING_ALLOCATE
1565
1566 @retval QCBOR_ERR_STRING_TOO_LONG
1567
1568 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1569
1570 @retval QCBOR_ERR_BAD_TYPE_7 X
1571
1572 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1573
1574 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1575
1576 @retval QCBOR_ERR_TOO_MANY_TAGS
1577
1578 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1579
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001580 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001581
1582 @retval QCBOR_ERR_NO_MORE_ITEMS
1583
1584 @retval QCBOR_ERR_BAD_BREAK
1585
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001586 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001587static QCBORError
1588QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001589{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001590 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001591 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001592
Laurence Lundblade642282a2020-06-23 12:00:33 -07001593 /*
1594 If out of bytes to consume, it is either the end of the top-level
1595 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001596
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1598 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1599 CBOR is exited, the length is set back to the top-level's length
1600 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001601 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001602 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001603 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001604 goto Done;
1605 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001606
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607 /*
1608 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001609 array. The check for a break ending indefinite length array is
1610 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001611 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001612 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001613 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001614 goto Done;
1615 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001616
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001617 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001618 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001619 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1620 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001621 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001622 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301623
Laurence Lundblade642282a2020-06-23 12:00:33 -07001624 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001625 Breaks ending arrays/maps are processed later in the call to
1626 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001627 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301628 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001629 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301630 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301631 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001632
Laurence Lundblade642282a2020-06-23 12:00:33 -07001633 /*
1634 Record the nesting level for this data item before processing any
1635 of decrementing and descending.
1636 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001637 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001638
Laurence Lundblade642282a2020-06-23 12:00:33 -07001639
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001640 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001641 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001642 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001643 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001644
Laurence Lundblade93d89472020-10-03 22:30:50 -07001645 Empty indefinite length maps and arrays are descended into, but
1646 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001647
1648 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649 encloses them so a decrement needs to be done for them too, but
1650 that is done only when all the items in them have been
1651 processed, not when they are opened with the exception of an
1652 empty map or array.
1653 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001654 QCBORError uDescendErr;
1655 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001656 pDecodedItem->uDataType,
1657 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001658 if(uDescendErr != QCBOR_SUCCESS) {
1659 /* This error is probably a traversal error and it
1660 overrides the non-traversal error. */
1661 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001662 goto Done;
1663 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001664 }
1665
Laurence Lundblade02625d42020-06-25 14:41:41 -07001666 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1667 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1668 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001669 /*
1670 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001671 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001672 - An empty definite length map or array
1673 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001674
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001675 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001676 definite length map/array and break detection for an indefinite
1677 length map/array. If the end of the map/array was reached, then
1678 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001679 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001680 QCBORError uAscendErr;
1681 uAscendErr = NestLevelAscender(me, true);
1682 if(uAscendErr != QCBOR_SUCCESS) {
1683 /* This error is probably a traversal error and it
1684 overrides the non-traversal error. */
1685 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001686 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001687 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301688 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001689
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001690 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001691 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001692 Tell the caller what level is next. This tells them what
1693 maps/arrays were closed out and makes it possible for them to
1694 reconstruct the tree with just the information returned in
1695 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001696 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001697 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001698 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001699 pDecodedItem->uNextNestLevel = 0;
1700 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001701 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001702 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001704Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001705 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001706}
1707
Laurence Lundblade9b334962020-08-27 10:55:53 -07001708static void ShiftTags(QCBORItem *pDecodedItem)
1709{
1710 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1711 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1712 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1713 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1714}
1715
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001716
Laurence Lundblade9b334962020-08-27 10:55:53 -07001717
Laurence Lundblade59289e52019-12-30 13:44:37 -08001718/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001719 The epoch formatted date. Turns lots of different forms of encoding
1720 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001721 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001722static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001723{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001724 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001725
1726 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1727
1728 switch (pDecodedItem->uDataType) {
1729
1730 case QCBOR_TYPE_INT64:
1731 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1732 break;
1733
1734 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001735 // This only happens for CBOR type 0 > INT64_MAX so it is
1736 // always an overflow.
1737 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1738 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001739 break;
1740
1741 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001742 case QCBOR_TYPE_FLOAT:
1743#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001744 {
1745 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001746 // conversion to an int64_t to be able to detect doubles that
1747 // are too large to fit into an int64_t. A double has 52
1748 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1749 // to a double actually causes a round up which is bad and
1750 // wrong for the comparison because it will allow conversion
1751 // of doubles that can't fit into a uint64_t. To remedy this
1752 // INT64_MAX - 0x7ff is used as the cutoff point because if
1753 // that value rounds up in conversion to double it will still
1754 // be less than INT64_MAX. 0x7ff is picked because it has 11
1755 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001756 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001757 // INT64_MAX seconds is on the order of 10 billion years, and
1758 // the earth is less than 5 billion years old, so for most
1759 // uses this conversion error won't occur even though doubles
1760 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001761 //
1762 // Without the 0x7ff there is a ~30 minute range of time
1763 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001764 // where this code would go wrong. Some compilers
1765 // will generate warnings or errors without the 0x7ff
1766 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001767 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1768 pDecodedItem->val.dfnum :
1769 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001770 if(isnan(d) ||
1771 d > (double)(INT64_MAX - 0x7ff) ||
1772 d < (double)(INT64_MIN + 0x7ff)) {
1773 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001774 goto Done;
1775 }
1776 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001777 pDecodedItem->val.epochDate.fSecondsFraction =
1778 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001780#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001781
Laurence Lundbladec7114722020-08-13 05:11:40 -07001782 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001783 goto Done;
1784
Laurence Lundblade9682a532020-06-06 18:33:04 -07001785#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001786 break;
1787
1788 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001789 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001790 goto Done;
1791 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001792
Laurence Lundblade59289e52019-12-30 13:44:37 -08001793 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1794
1795Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001796 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001797}
1798
1799
1800#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1801/*
1802 Decode decimal fractions and big floats.
1803
1804 When called pDecodedItem must be the array that is tagged as a big
1805 float or decimal fraction, the array that has the two members, the
1806 exponent and mantissa.
1807
1808 This will fetch and decode the exponent and mantissa and put the
1809 result back into pDecodedItem.
1810 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001811static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1813{
1814 QCBORError nReturn;
1815
1816 // --- Make sure it is an array; track nesting level of members ---
1817 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1818 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1819 goto Done;
1820 }
1821
1822 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001823 // definite length arrays, but not for indefnite. Instead remember
1824 // the nesting level the two integers must be at, which is one
1825 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001826 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1827
1828 // --- Is it a decimal fraction or a bigfloat? ---
1829 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1830 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1831
1832 // --- Get the exponent ---
1833 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001834 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 if(nReturn != QCBOR_SUCCESS) {
1836 goto Done;
1837 }
1838 if(exponentItem.uNestingLevel != nNestLevel) {
1839 // Array is empty or a map/array encountered when expecting an int
1840 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1841 goto Done;
1842 }
1843 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1844 // Data arriving as an unsigned int < INT64_MAX has been converted
1845 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1846 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1847 // will be too large for this to handle and thus an error that will
1848 // get handled in the next else.
1849 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1850 } else {
1851 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1852 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1853 goto Done;
1854 }
1855
1856 // --- Get the mantissa ---
1857 QCBORItem mantissaItem;
1858 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1859 if(nReturn != QCBOR_SUCCESS) {
1860 goto Done;
1861 }
1862 if(mantissaItem.uNestingLevel != nNestLevel) {
1863 // Mantissa missing or map/array encountered when expecting number
1864 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1865 goto Done;
1866 }
1867 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1868 // Data arriving as an unsigned int < INT64_MAX has been converted
1869 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1870 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1871 // will be too large for this to handle and thus an error that
1872 // will get handled in an else below.
1873 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001874 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1875 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001876 // Got a good big num mantissa
1877 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1878 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001879 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1880 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1881 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001882 } else {
1883 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1884 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1885 goto Done;
1886 }
1887
1888 // --- Check that array only has the two numbers ---
1889 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001890 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001891 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1892 goto Done;
1893 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001894 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001895
1896Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897 return nReturn;
1898}
1899#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1900
1901
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001902static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001903{
1904 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1905 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001906 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001907 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1908 } else {
1909 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001910
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001911 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001912
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001913 return QCBOR_SUCCESS;
1914}
1915
1916
Laurence Lundblade99615302020-11-29 11:19:47 -08001917/*
1918 * Table of CBOR tags whose content is either a text string or a byte
1919 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1920 * of uQCBORtype indicates the content should be a byte string rather
1921 * than a text string
1922 */
1923struct StringTagMapEntry {
1924 uint16_t uTagNumber;
1925 uint8_t uQCBORtype;
1926};
1927
1928#define IS_BYTE_STRING_BIT 0x80
1929#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1930
1931static const struct StringTagMapEntry StringTagMap[] = {
1932 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1933 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1934 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1935 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1936 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1937 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1938 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1939 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1940 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1941 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1942 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1943};
1944
1945
1946/*
1947 * Process the CBOR tags that whose content is a byte string or a text
1948 * string and for which the string is just passed on to the caller.
1949 *
1950 * This maps the CBOR tag to the QCBOR type and checks the content
1951 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001952 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001953 * possible.
1954 *
1955 * This returns QCBOR_SUCCESS if the tag was procssed,
1956 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1957 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1958 */
1959static inline
1960QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001961{
Laurence Lundblade99615302020-11-29 11:19:47 -08001962 /* This only works on tags that were not mapped; no need for other yet */
1963 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1964 return QCBOR_ERR_UNSUPPORTED;
1965 }
1966
1967 unsigned uIndex;
1968 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1969 if(StringTagMap[uIndex].uTagNumber == uTag) {
1970 break;
1971 }
1972 }
1973
1974 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1975 if(uQCBORType == QCBOR_TYPE_NONE) {
1976 /* repurpose this error to mean, not handled here */
1977 return QCBOR_ERR_UNSUPPORTED;
1978 }
1979
1980 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1981 if(uQCBORType & IS_BYTE_STRING_BIT) {
1982 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1983 }
1984
1985 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001986 return QCBOR_ERR_BAD_OPT_TAG;
1987 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001988
Laurence Lundblade99615302020-11-29 11:19:47 -08001989 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001990 return QCBOR_SUCCESS;
1991}
1992
1993
Laurence Lundblade59289e52019-12-30 13:44:37 -08001994/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001995 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1996 * but the whole tag was not decoded. Here, the whole tags (tag number
1997 * and tag content) that are supported by QCBOR are decoded. This is a
1998 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001999 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002000static QCBORError
2001QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002002{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002003 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002005 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2006 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007 goto Done;
2008 }
2009
Laurence Lundblade99615302020-11-29 11:19:47 -08002010 /* When there are no tag numbers for the item, this exits first
2011 * thing and effectively does nothing.
2012 *
2013 * This loops over all the tag numbers accumulated for this item
2014 * trying to decode and interpret them. This stops at the end of
2015 * the list or at the first tag number that can't be interpreted by
2016 * this code. This is effectively a recursive processing of the
2017 * tags number list that handles nested tags.
2018 */
2019 while(1) {
2020 /* Don't bother to unmap tags via QCBORITem.uTags since this
2021 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2022 */
2023 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024
Laurence Lundblade99615302020-11-29 11:19:47 -08002025 if(uTagToProcess == CBOR_TAG_INVALID16) {
2026 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002027 break;
2028
Laurence Lundblade99615302020-11-29 11:19:47 -08002029 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002030 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002031
Laurence Lundblade93d89472020-10-03 22:30:50 -07002032#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002033 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2034 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002035 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002036#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002037
Laurence Lundblade99615302020-11-29 11:19:47 -08002038 } else if(uTagToProcess == CBOR_TAG_MIME ||
2039 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002040 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002041
Laurence Lundblade99615302020-11-29 11:19:47 -08002042 } else {
2043 /* See if it is a pass-through byte/text string tag; process if so */
2044 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002045
Laurence Lundblade99615302020-11-29 11:19:47 -08002046 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2047 /* It wasn't a pass-through byte/text string tag so it is
2048 * an unknown tag. This is the exit from the loop on the
2049 * first unknown tag. It is a successful exit.
2050 */
2051 uReturn = QCBOR_SUCCESS;
2052 break;
2053 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002054 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002055
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002056 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002057 /* Error exit from the loop */
2058 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002059 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002060
2061 /* A tag was successfully processed, shift it out of the list of
2062 * tags returned. This is the loop increment.
2063 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002064 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002065 }
2066
2067Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002068 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002069}
2070
2071
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002072/*
2073 Public function, see header qcbor/qcbor_decode.h file
2074 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002075QCBORError
2076QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2077{
2078 QCBORError uErr;
2079 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2080 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002081 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2082 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2083 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002084 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002085}
2086
2087
2088/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002089 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002091QCBORError
2092QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2093{
2094 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2095 const UsefulInputBuf Save = pMe->InBuf;
2096
2097 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2098
2099 pMe->nesting = SaveNesting;
2100 pMe->InBuf = Save;
2101
2102 return uErr;
2103}
2104
2105
2106/*
2107 Public function, see header qcbor/qcbor_decode.h file
2108 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002109void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2110{
2111 if(pMe->uLastError != QCBOR_SUCCESS) {
2112 return;
2113 }
2114
2115 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2116}
2117
2118
2119/*
2120 Public function, see header qcbor/qcbor_decode.h file
2121 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002122QCBORError
2123QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2124 QCBORItem *pDecodedItem,
2125 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002126{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002127 QCBORError nReturn;
2128
2129 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2130 if(nReturn != QCBOR_SUCCESS) {
2131 return nReturn;
2132 }
2133
2134 if(pTags != NULL) {
2135 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002136 // Reverse the order because pTags is reverse of
2137 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002138 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2139 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002140 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002141 }
2142 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2143 return QCBOR_ERR_TOO_MANY_TAGS;
2144 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002145 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002146 pTags->uNumUsed++;
2147 }
2148 }
2149
2150 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002151}
2152
2153
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002154/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302155 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302156 next one down. If a layer has no work to do for a particular item
2157 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002158
Laurence Lundblade59289e52019-12-30 13:44:37 -08002159 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2160 tagged data items, turning them into the local C representation.
2161 For the most simple it is just associating a QCBOR_TYPE with the data. For
2162 the complex ones that an aggregate of data items, there is some further
2163 decoding and a little bit of recursion.
2164
2165 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302166 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302167 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002168 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002169
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302170 - GetNext_MapEntry -- This handles the combining of two
2171 items, the label and the data, that make up a map entry.
2172 It only does work on maps. It combines the label and data
2173 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002174
Laurence Lundblade59289e52019-12-30 13:44:37 -08002175 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2176 tags into bit flags associated with the data item. No actual decoding
2177 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002178
Laurence Lundblade59289e52019-12-30 13:44:37 -08002179 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302180 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302181 string allocater to create contiguous space for the item. It
2182 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002183
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2185 atomic data item has a "major type", an integer "argument" and optionally
2186 some content. For text and byte strings, the content is the bytes
2187 that make up the string. These are the smallest data items that are
2188 considered to be well-formed. The content may also be other data items in
2189 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002190
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002191 Roughly this takes 300 bytes of stack for vars. Need to
2192 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302194 */
2195
2196
2197/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002198 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002199 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002200bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002201 const QCBORItem *pItem,
2202 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002203{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002204 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2205 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002206 break;
2207 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002208 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002209 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002210 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002211 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002212
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002213 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002214}
2215
2216
2217/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002218 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002219 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002220QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002221{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002222 QCBORError uReturn = me->uLastError;
2223
2224 if(uReturn != QCBOR_SUCCESS) {
2225 goto Done;
2226 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002228 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002229 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002230 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002231 goto Done;
2232 }
2233
2234 // Error out if not all the bytes are consumed
2235 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002236 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002237 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002238
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002239Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002240#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302241 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002242 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002243 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002244#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundblade085d7952020-07-24 10:26:30 -07002246 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002247}
2248
2249
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002250/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002251 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002252*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002253// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002254uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2255 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002256 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002257{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002258 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2259 return CBOR_TAG_INVALID64;
2260 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002261 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2262 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002263 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002264 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002265 }
2266}
2267
Laurence Lundblade9b334962020-08-27 10:55:53 -07002268/*
2269 Public function, see header qcbor/qcbor_decode.h file
2270*/
2271uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2272 uint32_t uIndex)
2273{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002274 if(pMe->uLastError != QCBOR_SUCCESS) {
2275 return CBOR_TAG_INVALID64;
2276 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002277 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2278 return CBOR_TAG_INVALID64;
2279 } else {
2280 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2281 }
2282}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002283
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002284/*
2285
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002286Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002287
Laurence Lundbladeee851742020-01-08 08:37:05 -08002288 - Hit end of input before it was expected while decoding type and
2289 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002290
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002291 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002292
Laurence Lundbladeee851742020-01-08 08:37:05 -08002293 - Hit end of input while decoding a text or byte string
2294 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002295
Laurence Lundbladeee851742020-01-08 08:37:05 -08002296 - Encountered conflicting tags -- e.g., an item is tagged both a date
2297 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002298
Laurence Lundbladeee851742020-01-08 08:37:05 -08002299 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002300 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002301
Laurence Lundbladeee851742020-01-08 08:37:05 -08002302 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002303 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002304
Laurence Lundbladeee851742020-01-08 08:37:05 -08002305 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2306 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002307
Laurence Lundbladeee851742020-01-08 08:37:05 -08002308 - The type of a map label is not a string or int
2309 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002310
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002311 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002312
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002313 */
2314
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002315
2316
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002317#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002318
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002319/* ===========================================================================
2320 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002321
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002322 This implements a simple sting allocator for indefinite length
2323 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2324 implements the function type QCBORStringAllocate and allows easy
2325 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002326
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002327 This particular allocator is built-in for convenience. The caller
2328 can implement their own. All of this following code will get
2329 dead-stripped if QCBORDecode_SetMemPool() is not called.
2330
2331 This is a very primitive memory allocator. It does not track
2332 individual allocations, only a high-water mark. A free or
2333 reallocation must be of the last chunk allocated.
2334
2335 The size of the pool and offset to free memory are packed into the
2336 first 8 bytes of the memory pool so we don't have to keep them in
2337 the decode context. Since the address of the pool may not be
2338 aligned, they have to be packed and unpacked as if they were
2339 serialized data of the wire or such.
2340
2341 The sizes packed in are uint32_t to be the same on all CPU types
2342 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002343 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002344
2345
Laurence Lundbladeee851742020-01-08 08:37:05 -08002346static inline int
2347MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002348{
2349 // Use of UsefulInputBuf is overkill, but it is convenient.
2350 UsefulInputBuf UIB;
2351
Laurence Lundbladeee851742020-01-08 08:37:05 -08002352 // Just assume the size here. It was checked during SetUp so
2353 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002354 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002355 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2356 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2357 return UsefulInputBuf_GetError(&UIB);
2358}
2359
2360
Laurence Lundbladeee851742020-01-08 08:37:05 -08002361static inline int
2362MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002363{
2364 // Use of UsefulOutBuf is overkill, but convenient. The
2365 // length check performed here is useful.
2366 UsefulOutBuf UOB;
2367
2368 UsefulOutBuf_Init(&UOB, Pool);
2369 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2370 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2371 return UsefulOutBuf_GetError(&UOB);
2372}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002373
2374
2375/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002376 Internal function for an allocation, reallocation free and destuct.
2377
2378 Having only one function rather than one each per mode saves space in
2379 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002380
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002381 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2382 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002383static UsefulBuf
2384MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002385{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002386 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002387
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002388 uint32_t uPoolSize;
2389 uint32_t uFreeOffset;
2390
2391 if(uNewSize > UINT32_MAX) {
2392 // This allocator is only good up to 4GB. This check should
2393 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2394 goto Done;
2395 }
2396 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2397
2398 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2399 goto Done;
2400 }
2401
2402 if(uNewSize) {
2403 if(pMem) {
2404 // REALLOCATION MODE
2405 // Calculate pointer to the end of the memory pool. It is
2406 // assumed that pPool + uPoolSize won't wrap around by
2407 // assuming the caller won't pass a pool buffer in that is
2408 // not in legitimate memory space.
2409 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2410
2411 // Check that the pointer for reallocation is in the range of the
2412 // pool. This also makes sure that pointer math further down
2413 // doesn't wrap under or over.
2414 if(pMem >= pPool && pMem < pPoolEnd) {
2415 // Offset to start of chunk for reallocation. This won't
2416 // wrap under because of check that pMem >= pPool. Cast
2417 // is safe because the pool is always less than UINT32_MAX
2418 // because of check in QCBORDecode_SetMemPool().
2419 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2420
2421 // Check to see if the allocation will fit. uPoolSize -
2422 // uMemOffset will not wrap under because of check that
2423 // pMem is in the range of the uPoolSize by check above.
2424 if(uNewSize <= uPoolSize - uMemOffset) {
2425 ReturnValue.ptr = pMem;
2426 ReturnValue.len = uNewSize;
2427
2428 // Addition won't wrap around over because uNewSize was
2429 // checked to be sure it is less than the pool size.
2430 uFreeOffset = uMemOffset + uNewSize32;
2431 }
2432 }
2433 } else {
2434 // ALLOCATION MODE
2435 // uPoolSize - uFreeOffset will not underflow because this
2436 // pool implementation makes sure uFreeOffset is always
2437 // smaller than uPoolSize through this check here and
2438 // reallocation case.
2439 if(uNewSize <= uPoolSize - uFreeOffset) {
2440 ReturnValue.len = uNewSize;
2441 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002442 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002443 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002444 }
2445 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002446 if(pMem) {
2447 // FREE MODE
2448 // Cast is safe because of limit on pool size in
2449 // QCBORDecode_SetMemPool()
2450 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2451 } else {
2452 // DESTRUCT MODE
2453 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002454 }
2455 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002456
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002457 UsefulBuf Pool = {pPool, uPoolSize};
2458 MemPool_Pack(Pool, uFreeOffset);
2459
2460Done:
2461 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002462}
2463
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002464
Laurence Lundbladef6531662018-12-04 10:42:22 +09002465/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002466 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002467 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002468QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2469 UsefulBuf Pool,
2470 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002471{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002472 // The pool size and free mem offset are packed into the beginning
2473 // of the pool memory. This compile time check make sure the
2474 // constant in the header is correct. This check should optimize
2475 // down to nothing.
2476 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002477 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002478 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002479
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002480 // The pool size and free offset packed in to the beginning of pool
2481 // memory are only 32-bits. This check will optimize out on 32-bit
2482 // machines.
2483 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002484 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002485 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002486
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002487 // This checks that the pool buffer given is big enough.
2488 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002489 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002490 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002491
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002492 pMe->StringAllocator.pfAllocator = MemPool_Function;
2493 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2494 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002495
Laurence Lundblade30816f22018-11-10 13:40:22 +07002496 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002497}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002498#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002499
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002500
2501
Laurence Lundblade9b334962020-08-27 10:55:53 -07002502static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2503{
2504 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2505}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002506
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002507
2508/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002509 Consume an entire map or array (and do next to
2510 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002511 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002512static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002513ConsumeItem(QCBORDecodeContext *pMe,
2514 const QCBORItem *pItemToConsume,
2515 uint_fast8_t *puNextNestLevel)
2516{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002517 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002518 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002519
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002520 // If it is a map or array, this will tell if it is empty.
2521 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2522
2523 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2524 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525
Laurence Lundblade1341c592020-04-11 14:19:05 -07002526 /* This works for definite and indefinite length
2527 * maps and arrays by using the nesting level
2528 */
2529 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002530 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002531 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002532 goto Done;
2533 }
2534 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002535
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002536 *puNextNestLevel = Item.uNextNestLevel;
2537
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002538 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002539
Laurence Lundblade1341c592020-04-11 14:19:05 -07002540 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002541 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002542 /* Just pass the nesting level through */
2543 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2544
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002545 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002546 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002547
2548Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002549 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002550}
2551
2552
Laurence Lundblade1341c592020-04-11 14:19:05 -07002553/* Return true if the labels in Item1 and Item2 are the same.
2554 Works only for integer and string labels. Returns false
2555 for any other type. */
2556static inline bool
2557MatchLabel(QCBORItem Item1, QCBORItem Item2)
2558{
2559 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2560 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2561 return true;
2562 }
2563 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002564 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002565 return true;
2566 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002567 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002568 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2569 return true;
2570 }
2571 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2572 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2573 return true;
2574 }
2575 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002576
Laurence Lundblade1341c592020-04-11 14:19:05 -07002577 /* Other label types are never matched */
2578 return false;
2579}
2580
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002581
2582/*
2583 Returns true if Item1 and Item2 are the same type
2584 or if either are of QCBOR_TYPE_ANY.
2585 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002586static inline bool
2587MatchType(QCBORItem Item1, QCBORItem Item2)
2588{
2589 if(Item1.uDataType == Item2.uDataType) {
2590 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002591 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002592 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002593 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002594 return true;
2595 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002596 return false;
2597}
2598
2599
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002600/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002601 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002602
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002603 @param[in] pMe The decode context to search.
2604 @param[in,out] pItemArray The items to search for and the items found.
2605 @param[out] puOffset Byte offset of last item matched.
2606 @param[in] pCBContext Context for the not-found item call back.
2607 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002608
2609 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2610
Laurence Lundblade93d89472020-10-03 22:30:50 -07002611 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2612 were found for one of the labels being
2613 search for. This duplicate detection is
2614 only performed for items in pItemArray,
2615 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002616
Laurence Lundblade93d89472020-10-03 22:30:50 -07002617 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2618 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002619
2620 @retval Also errors returned by QCBORDecode_GetNext().
2621
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002622 On input pItemArray contains a list of labels and data types
2623 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002624
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002625 On output the fully retrieved items are filled in with
2626 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002627
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002628 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002629
2630 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002631 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002632static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002633MapSearch(QCBORDecodeContext *pMe,
2634 QCBORItem *pItemArray,
2635 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002636 void *pCBContext,
2637 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002638{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002639 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002640 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002641
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002642 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002643 uReturn = pMe->uLastError;
2644 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002645 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002646
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002647 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002648 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2649 /* QCBOR_TYPE_NONE as first item indicates just looking
2650 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002651 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2652 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002653 }
2654
Laurence Lundblade085d7952020-07-24 10:26:30 -07002655 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2656 // It is an empty bounded array or map
2657 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2658 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002659 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002660 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002661 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002662 // Nothing is ever found in an empty array or map. All items
2663 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002664 uReturn = QCBOR_SUCCESS;
2665 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002666 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002667 }
2668
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002669 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002670 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2671
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002672 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002673 UsefulInputBuf_Seek(&(pMe->InBuf),
2674 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002675
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002676 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002677 Loop over all the items in the map or array. Each item
2678 could be a map or array, but label matching is only at
2679 the main level. This handles definite and indefinite
2680 length maps and arrays. The only reason this is ever
2681 called on arrays is to find their end position.
2682
2683 This will always run over all items in order to do
2684 duplicate detection.
2685
2686 This will exit with failure if it encounters an
2687 unrecoverable error, but continue on for recoverable
2688 errors.
2689
2690 If a recoverable error occurs on a matched item, then
2691 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002692 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002693 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002694 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002695 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002696 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002697 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002698
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002699 /* Get the item */
2700 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002701 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2702 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002703 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002704 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705 goto Done;
2706 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002707 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002708 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002709 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002710 goto Done;
2711 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002712
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002713 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002714 bool bMatched = false;
2715 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2716 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002717 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002718 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2719 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002720 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002722 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002723 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002724 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002725 goto Done;
2726 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002727
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002728 if(uResult != QCBOR_SUCCESS) {
2729 uReturn = uResult;
2730 goto Done;
2731 }
2732
Laurence Lundblade1341c592020-04-11 14:19:05 -07002733 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002734 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002735 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002736 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002737 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002738 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002739 bMatched = true;
2740 }
2741 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002742
2743
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002744 if(!bMatched && pfCallback != NULL) {
2745 /*
2746 Call the callback on unmatched labels.
2747 (It is tempting to do duplicate detection here, but that would
2748 require dynamic memory allocation because the number of labels
2749 that might be encountered is unbounded.)
2750 */
2751 uReturn = (*pfCallback)(pCBContext, &Item);
2752 if(uReturn != QCBOR_SUCCESS) {
2753 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754 }
2755 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002756
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002757 /*
2758 Consume the item whether matched or not. This
2759 does the work of traversing maps and array and
2760 everything in them. In this loop only the
2761 items at the current nesting level are examined
2762 to match the labels.
2763 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002764 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002765 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766 goto Done;
2767 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002768
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002769 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002770
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002771 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002772
2773 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002774
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002775 // Check here makes sure that this won't accidentally be
2776 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002777 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002778 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2779 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002780 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2781 goto Done;
2782 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002783 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2784 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002785
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002786 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002787 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2788
2789 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002790 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002791 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002792 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002793 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2794 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002795 }
2796 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002797
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002798 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002799}
2800
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002801
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002802/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002803 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002804*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002805void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2806 int64_t nLabel,
2807 uint8_t uQcborType,
2808 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002810 if(pMe->uLastError != QCBOR_SUCCESS) {
2811 return;
2812 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002813
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002814 QCBORItem OneItemSeach[2];
2815 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2816 OneItemSeach[0].label.int64 = nLabel;
2817 OneItemSeach[0].uDataType = uQcborType;
2818 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002819
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002820 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002821
2822 *pItem = OneItemSeach[0];
2823
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002824 if(uReturn != QCBOR_SUCCESS) {
2825 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002826 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002827 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002828 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829 }
2830
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002831 Done:
2832 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002833}
2834
2835
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002836/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002837 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002838*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002839void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2840 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002841 uint8_t uQcborType,
2842 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002844 if(pMe->uLastError != QCBOR_SUCCESS) {
2845 return;
2846 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002847
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002848 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002849 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2850 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2851 OneItemSeach[0].uDataType = uQcborType;
2852 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002853
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002854 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2855 if(uReturn != QCBOR_SUCCESS) {
2856 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002857 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002858 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002859 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002860 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002861 }
2862
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002863 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002864
2865Done:
2866 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002867}
2868
2869
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002870
Laurence Lundblade93d89472020-10-03 22:30:50 -07002871static QCBORError
2872CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002873{
2874 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2875 if(uDataType == puTypeList[i]) {
2876 return QCBOR_SUCCESS;
2877 }
2878 }
2879 return QCBOR_ERR_UNEXPECTED_TYPE;
2880}
2881
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002882
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002883/**
2884 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002885 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002886
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002887 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2888 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002889
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002890 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2891 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002892 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002893static QCBORError
2894CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002895{
2896 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2897 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2898 /* There are tags that QCBOR couldn't process on this item and
2899 the caller has told us there should not be. */
2900 return QCBOR_ERR_UNEXPECTED_TYPE;
2901 }
2902
2903 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2904 const int nItemType = pItem->uDataType;
2905
2906 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2907 // Must match the tag and only the tag
2908 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2909 }
2910
2911 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2912 if(uReturn == QCBOR_SUCCESS) {
2913 return QCBOR_SUCCESS;
2914 }
2915
2916 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2917 /* Must match the content type and only the content type.
2918 There was no match just above so it is a fail. */
2919 return QCBOR_ERR_UNEXPECTED_TYPE;
2920 }
2921
2922 /* If here it can match either the tag or the content
2923 and it hasn't matched the content, so the end
2924 result is whether it matches the tag. This is
2925 also the case that the CBOR standard discourages. */
2926
2927 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2928}
2929
Laurence Lundblade9b334962020-08-27 10:55:53 -07002930
Laurence Lundblade9b334962020-08-27 10:55:53 -07002931
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002932// This could be semi-private if need be
2933static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002934void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2935 int64_t nLabel,
2936 TagSpecification TagSpec,
2937 QCBORItem *pItem)
2938{
2939 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2940 if(pMe->uLastError != QCBOR_SUCCESS) {
2941 return;
2942 }
2943
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002944 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002945}
2946
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002947
2948// This could be semi-private if need be
2949static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002950void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2951 const char *szLabel,
2952 TagSpecification TagSpec,
2953 QCBORItem *pItem)
2954{
2955 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2956 if(pMe->uLastError != QCBOR_SUCCESS) {
2957 return;
2958 }
2959
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002960 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002961}
2962
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002963// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002964void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2965 int64_t nLabel,
2966 TagSpecification TagSpec,
2967 UsefulBufC *pString)
2968{
2969 QCBORItem Item;
2970 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2971 if(pMe->uLastError == QCBOR_SUCCESS) {
2972 *pString = Item.val.string;
2973 }
2974}
2975
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002976// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002977void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2978 const char * szLabel,
2979 TagSpecification TagSpec,
2980 UsefulBufC *pString)
2981{
2982 QCBORItem Item;
2983 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2984 if(pMe->uLastError == QCBOR_SUCCESS) {
2985 *pString = Item.val.string;
2986 }
2987}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002988
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002989/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002990 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002991*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002992void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002993{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002994 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2995 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002996}
2997
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002998/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002999 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003000*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003001void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3002 QCBORItem *pItemList,
3003 void *pCallbackCtx,
3004 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003005{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003006 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3007 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003008}
3009
3010
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003011/**
3012 * @brief Search for a map/array by label and enter it
3013 *
3014 * @param[in] pMe The decode context.
3015 * @param[in] pSearch The map/array to search for.
3016 *
3017 * @c pSearch is expected to contain one item of type map or array
3018 * with the label specified. The current bounded map will be searched for
3019 * this and if found will be entered.
3020 *
3021 * If the label is not found, or the item found is not a map or array,
3022 * the error state is set.
3023 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003024static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003025{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003026 // The first item in pSearch is the one that is to be
3027 // entered. It should be the only one filled in. Any other
3028 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003029 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003030 return;
3031 }
3032
3033 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003034 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003035 if(pMe->uLastError != QCBOR_SUCCESS) {
3036 return;
3037 }
3038
Laurence Lundblade9b334962020-08-27 10:55:53 -07003039 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003040 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003041 return;
3042 }
3043
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003044 /*
3045 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3046 * next item for the pre-order traversal cursor to be the map/array
3047 * found by MapSearch(). The next few lines of code force the
3048 * cursor to that.
3049 *
3050 * There is no need to retain the old cursor because
3051 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3052 * beginning of the map/array being entered.
3053 *
3054 * The cursor is forced by: 1) setting the input buffer position to
3055 * the item offset found by MapSearch(), 2) setting the map/array
3056 * counter to the total in the map/array, 3) setting the nesting
3057 * level. Setting the map/array counter to the total is not
3058 * strictly correct, but this is OK because this cursor only needs
3059 * to be used to get one item and MapSearch() has already found it
3060 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003061 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003062 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003063
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003064 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3065
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003066 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003067
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003068 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003069}
3070
3071
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003072/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003073 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003074*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003075void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003076{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003077 QCBORItem OneItemSeach[2];
3078 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3079 OneItemSeach[0].label.int64 = nLabel;
3080 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3081 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003082
Laurence Lundblade9b334962020-08-27 10:55:53 -07003083 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003084 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003085}
3086
3087
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003088/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003089 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003090*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003091void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003092{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003093 QCBORItem OneItemSeach[2];
3094 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3095 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3096 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3097 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003098
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003099 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003100}
3101
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003102/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003103 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003104*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003105void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003106{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003107 QCBORItem OneItemSeach[2];
3108 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3109 OneItemSeach[0].label.int64 = nLabel;
3110 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3111 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003112
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003113 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003114}
3115
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003116/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003117 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003118*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003119void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3120{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003121 QCBORItem OneItemSeach[2];
3122 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3123 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3124 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3125 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003126
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003127 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003128}
3129
3130
Laurence Lundblade02625d42020-06-25 14:41:41 -07003131// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003132void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003133{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003134 QCBORError uErr;
3135
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003136 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003137 if(pMe->uLastError != QCBOR_SUCCESS) {
3138 // Already in error state; do nothing.
3139 return;
3140 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003141
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003142 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003143 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003144 uErr = QCBORDecode_GetNext(pMe, &Item);
3145 if(uErr != QCBOR_SUCCESS) {
3146 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003147 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003148 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003149 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3150 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003151 }
3152
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003153 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003154
3155
Laurence Lundbladef0499502020-08-01 11:55:57 -07003156 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003157 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003158 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3159 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003160 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003161 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3162 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003163 // Special case to increment nesting level for zero-length maps
3164 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003165 DecodeNesting_Descend(&(pMe->nesting), uType);
3166 }
3167
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003168 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003169
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003170 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3171 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003172
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003173 if(pItem != NULL) {
3174 *pItem = Item;
3175 }
3176
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003177Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003178 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003179}
3180
Laurence Lundblade02625d42020-06-25 14:41:41 -07003181
3182/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003183 This is the common work for exiting a level that is a bounded map,
3184 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003185
3186 One chunk of work is to set up the pre-order traversal so it is at
3187 the item just after the bounded map, array or bstr that is being
3188 exited. This is somewhat complex.
3189
3190 The other work is to level-up the bounded mode to next higest bounded
3191 mode or the top level if there isn't one.
3192 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003193static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003194ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003195{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003196 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003197
Laurence Lundblade02625d42020-06-25 14:41:41 -07003198 /*
3199 First the pre-order-traversal byte offset is positioned to the
3200 item just after the bounded mode item that was just consumed.
3201 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003202 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3203
Laurence Lundblade02625d42020-06-25 14:41:41 -07003204 /*
3205 Next, set the current nesting level to one above the bounded level
3206 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003207
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 DecodeNesting_CheckBoundedType() is always called before this and
3209 makes sure pCurrentBounded is valid.
3210 */
3211 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3212
3213 /*
3214 This does the complex work of leveling up the pre-order traversal
3215 when the end of a map or array or another bounded level is
3216 reached. It may do nothing, or ascend all the way to the top
3217 level.
3218 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003219 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003220 if(uErr != QCBOR_SUCCESS) {
3221 goto Done;
3222 }
3223
Laurence Lundblade02625d42020-06-25 14:41:41 -07003224 /*
3225 This makes the next highest bounded level the current bounded
3226 level. If there is no next highest level, then no bounded mode is
3227 in effect.
3228 */
3229 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003230
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003231 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003232
3233Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003234 return uErr;
3235}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003236
Laurence Lundblade02625d42020-06-25 14:41:41 -07003237
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003238// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003239void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003240{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003241 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003242 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003243 return;
3244 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003245
Laurence Lundblade02625d42020-06-25 14:41:41 -07003246 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003247
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003248 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003249 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003250 goto Done;
3251 }
3252
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 /*
3254 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003255 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003256 from previous map search, then do a dummy search.
3257 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003258 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003259 QCBORItem Dummy;
3260 Dummy.uLabelType = QCBOR_TYPE_NONE;
3261 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3262 if(uErr != QCBOR_SUCCESS) {
3263 goto Done;
3264 }
3265 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003266
Laurence Lundblade02625d42020-06-25 14:41:41 -07003267 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003268
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003269Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003270 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003271}
3272
3273
Laurence Lundblade1341c592020-04-11 14:19:05 -07003274
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003275static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003276 const QCBORItem *pItem,
3277 uint8_t uTagRequirement,
3278 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003279{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003280 if(pBstr) {
3281 *pBstr = NULLUsefulBufC;
3282 }
3283
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003284 if(pMe->uLastError != QCBOR_SUCCESS) {
3285 // Already in error state; do nothing.
3286 return pMe->uLastError;
3287 }
3288
3289 QCBORError uError = QCBOR_SUCCESS;
3290
3291 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3292 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3293 goto Done;;
3294 }
3295
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003296 const TagSpecification TagSpec =
3297 {
3298 uTagRequirement,
3299 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3300 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3301 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003302
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003303 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003304 if(uError != QCBOR_SUCCESS) {
3305 goto Done;
3306 }
3307
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003308 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003309 // Reverse the decrement done by GetNext() for the bstr so the
3310 // increment in NestLevelAscender() called by ExitBoundedLevel()
3311 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003312 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003313 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003314
3315 if(pBstr) {
3316 *pBstr = pItem->val.string;
3317 }
3318
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003319 // This saves the current length of the UsefulInputBuf and then
3320 // narrows the UsefulInputBuf to start and length of the wrapped
3321 // CBOR that is being entered.
3322 //
3323 // This makes sure the length is less than
3324 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3325 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3326 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3327 // the casts safe. uEndOfBstr will always be less than
3328 // uPreviousLength because of the way UsefulInputBuf works so there
3329 // is no need to check it. There is also a range check in the
3330 // seek.
3331 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003332 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003333 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003334 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003335 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003336 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003337 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003338 goto Done;
3339 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003340 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003341 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003342 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003343
Laurence Lundblade02625d42020-06-25 14:41:41 -07003344 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003345 (uint32_t)uPreviousLength,
3346 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003347Done:
3348 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003349}
3350
3351
Laurence Lundblade02625d42020-06-25 14:41:41 -07003352/*
3353 Public function, see header qcbor/qcbor_decode.h file
3354 */
3355void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003356 uint8_t uTagRequirement,
3357 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003358{
3359 if(pMe->uLastError != QCBOR_SUCCESS) {
3360 // Already in error state; do nothing.
3361 return;
3362 }
3363
3364 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003365 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003366 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3367 if(pMe->uLastError != QCBOR_SUCCESS) {
3368 return;
3369 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003370
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003371 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003372 &Item,
3373 uTagRequirement,
3374 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003375}
3376
3377
Laurence Lundblade02625d42020-06-25 14:41:41 -07003378/*
3379 Public function, see header qcbor/qcbor_decode.h file
3380 */
3381void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003383 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003384 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003385{
3386 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003387 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003388
Laurence Lundblade93d89472020-10-03 22:30:50 -07003389 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3390 &Item,
3391 uTagRequirement,
3392 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003393}
3394
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003395
Laurence Lundblade02625d42020-06-25 14:41:41 -07003396/*
3397 Public function, see header qcbor/qcbor_decode.h file
3398 */
3399void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003400 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003401 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003402 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003403{
3404 QCBORItem Item;
3405 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3406
Laurence Lundblade93d89472020-10-03 22:30:50 -07003407 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3408 &Item,
3409 uTagRequirement,
3410 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003411}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003412
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003413
Laurence Lundblade02625d42020-06-25 14:41:41 -07003414/*
3415 Public function, see header qcbor/qcbor_decode.h file
3416 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003417void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003418{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003419 if(pMe->uLastError != QCBOR_SUCCESS) {
3420 // Already in error state; do nothing.
3421 return;
3422 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003423
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003424 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003425 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003426 return;
3427 }
3428
3429 /*
3430 Reset the length of the UsefulInputBuf to what it was before
3431 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003432 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003433 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003434 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003435
3436
Laurence Lundblade02625d42020-06-25 14:41:41 -07003437 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003438 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003439}
3440
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003441
Laurence Lundbladee6430642020-03-14 21:15:44 -07003442
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003443
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003444
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003445
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003446
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003447
Laurence Lundblade93d89472020-10-03 22:30:50 -07003448static QCBORError
3449InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003450{
3451 switch(pItem->uDataType) {
3452 case QCBOR_TYPE_TRUE:
3453 *pBool = true;
3454 return QCBOR_SUCCESS;
3455 break;
3456
3457 case QCBOR_TYPE_FALSE:
3458 *pBool = false;
3459 return QCBOR_SUCCESS;
3460 break;
3461
3462 default:
3463 return QCBOR_ERR_UNEXPECTED_TYPE;
3464 break;
3465 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003466 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003467}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003468
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003469
Laurence Lundblade9b334962020-08-27 10:55:53 -07003470
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003471/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003472 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003473*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003474void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003475{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003476 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003477 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003478 return;
3479 }
3480
Laurence Lundbladec4537442020-04-14 18:53:22 -07003481 QCBORError nError;
3482 QCBORItem Item;
3483
3484 nError = QCBORDecode_GetNext(pMe, &Item);
3485 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003486 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003487 return;
3488 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003489 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003490}
3491
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003492
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003493/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003494 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003495*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003496void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003497{
3498 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003499 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003500
Laurence Lundblade9b334962020-08-27 10:55:53 -07003501 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003502}
3503
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003504
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003505/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003506 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003507*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003508void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3509{
3510 QCBORItem Item;
3511 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3512
Laurence Lundblade9b334962020-08-27 10:55:53 -07003513 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003514}
3515
3516
3517
Laurence Lundbladec7114722020-08-13 05:11:40 -07003518
3519static void ProcessEpochDate(QCBORDecodeContext *pMe,
3520 QCBORItem *pItem,
3521 uint8_t uTagRequirement,
3522 int64_t *pnTime)
3523{
3524 if(pMe->uLastError != QCBOR_SUCCESS) {
3525 // Already in error state, do nothing
3526 return;
3527 }
3528
3529 QCBORError uErr;
3530
3531 const TagSpecification TagSpec =
3532 {
3533 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003534 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3535 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003536 };
3537
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003538 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003539 if(uErr != QCBOR_SUCCESS) {
3540 goto Done;
3541 }
3542
3543 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3544 uErr = DecodeDateEpoch(pItem);
3545 if(uErr != QCBOR_SUCCESS) {
3546 goto Done;
3547 }
3548 }
3549
Laurence Lundblade9b334962020-08-27 10:55:53 -07003550 // Save the tags in the last item's tags in the decode context
3551 // for QCBORDecode_GetNthTagOfLast()
3552 CopyTags(pMe, pItem);
3553
Laurence Lundbladec7114722020-08-13 05:11:40 -07003554 *pnTime = pItem->val.epochDate.nSeconds;
3555
3556Done:
3557 pMe->uLastError = (uint8_t)uErr;
3558}
3559
3560
3561void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003562 uint8_t uTagRequirement,
3563 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003564{
3565 if(pMe->uLastError != QCBOR_SUCCESS) {
3566 // Already in error state, do nothing
3567 return;
3568 }
3569
3570 QCBORItem Item;
3571 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3572
3573 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3574}
3575
3576
3577void
3578QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3579 int64_t nLabel,
3580 uint8_t uTagRequirement,
3581 int64_t *pnTime)
3582{
3583 QCBORItem Item;
3584 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3585 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3586}
3587
3588
3589void
3590QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3591 const char *szLabel,
3592 uint8_t uTagRequirement,
3593 int64_t *pnTime)
3594{
3595 QCBORItem Item;
3596 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3597 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3598}
3599
3600
3601
3602
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003603void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3604 TagSpecification TagSpec,
3605 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003606{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003607 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003608 // Already in error state, do nothing
3609 return;
3610 }
3611
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003612 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003613 QCBORItem Item;
3614
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003615 uError = QCBORDecode_GetNext(pMe, &Item);
3616 if(uError != QCBOR_SUCCESS) {
3617 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003618 return;
3619 }
3620
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003621 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003622
3623 if(pMe->uLastError == QCBOR_SUCCESS) {
3624 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003625 } else {
3626 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627 }
3628}
3629
Laurence Lundbladec4537442020-04-14 18:53:22 -07003630
3631
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003632
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003633static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003634 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003635 UsefulBufC *pValue,
3636 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003637{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003638 const TagSpecification TagSpec =
3639 {
3640 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003641 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3642 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003643 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003644
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003645 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003646 if(uErr != QCBOR_SUCCESS) {
3647 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003648 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003649
3650 *pValue = pItem->val.string;
3651
3652 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3653 *pbIsNegative = false;
3654 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3655 *pbIsNegative = true;
3656 }
3657
3658 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003659}
3660
3661
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003662/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003663 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003664 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003665void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3666 uint8_t uTagRequirement,
3667 UsefulBufC *pValue,
3668 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003669{
3670 if(pMe->uLastError != QCBOR_SUCCESS) {
3671 // Already in error state, do nothing
3672 return;
3673 }
3674
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003675 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003676 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3677 if(uError != QCBOR_SUCCESS) {
3678 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003679 return;
3680 }
3681
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003682 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003683}
3684
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003685
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003686/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003687 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003688*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003689void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3690 int64_t nLabel,
3691 uint8_t uTagRequirement,
3692 UsefulBufC *pValue,
3693 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003694{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003695 QCBORItem Item;
3696 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003697 if(pMe->uLastError != QCBOR_SUCCESS) {
3698 return;
3699 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003700
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003701 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003702}
3703
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003704
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003705/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003706 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003707*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003708void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3709 const char *szLabel,
3710 uint8_t uTagRequirement,
3711 UsefulBufC *pValue,
3712 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003713{
3714 QCBORItem Item;
3715 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003716 if(pMe->uLastError != QCBOR_SUCCESS) {
3717 return;
3718 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003719
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003720 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003721}
3722
3723
3724
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003725
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003726// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003727QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3728 const QCBORItem *pItem,
3729 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003730 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003731{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003732 const TagSpecification TagSpecText =
3733 {
3734 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003735 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3736 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003737 };
3738 const TagSpecification TagSpecBinary =
3739 {
3740 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003741 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3742 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003743 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003744
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003745 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003746
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003747 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003748 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003749 if(pbIsTag257 != NULL) {
3750 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003751 }
3752 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003753 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003754 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003755 if(pbIsTag257 != NULL) {
3756 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003757 }
3758 uReturn = QCBOR_SUCCESS;
3759
3760 } else {
3761 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3762 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003763
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003764 return uReturn;
3765}
3766
Laurence Lundblade93d89472020-10-03 22:30:50 -07003767// Improvement: add methods for wrapped CBOR, a simple alternate
3768// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003769
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003770
3771
3772
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003773#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003774
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003775typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003776
3777
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003778// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003779static QCBORError
3780Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003781{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003782 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003784 if(uResult != 0) {
3785 /* This loop will run a maximum of 19 times because
3786 * UINT64_MAX < 10 ^^ 19. More than that will cause
3787 * exit with the overflow error
3788 */
3789 for(; nExponent > 0; nExponent--) {
3790 if(uResult > UINT64_MAX / 10) {
3791 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3792 }
3793 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003794 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003795
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003796 for(; nExponent < 0; nExponent++) {
3797 uResult = uResult / 10;
3798 if(uResult == 0) {
3799 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3800 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003801 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003802 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003803 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804
3805 *puResult = uResult;
3806
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003807 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003808}
3809
3810
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003811// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003812static QCBORError
3813Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003814{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003815 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003816
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003817 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003818
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003819 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003820 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003821 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003822 */
3823 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003824 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003825 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003826 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003827 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003828 nExponent--;
3829 }
3830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003831 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003832 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003833 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3834 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003835 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003836 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003837 }
3838
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003839 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 return QCBOR_SUCCESS;
3842}
3843
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003844
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003845/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003846 Compute value with signed mantissa and signed result. Works with
3847 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003848 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003849static inline QCBORError ExponentiateNN(int64_t nMantissa,
3850 int64_t nExponent,
3851 int64_t *pnResult,
3852 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003853{
3854 uint64_t uResult;
3855
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003856 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003857 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003858 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3859
3860 // Do the exponentiation of the positive mantissa
3861 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3862 if(uReturn) {
3863 return uReturn;
3864 }
3865
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003866
Laurence Lundblade983500d2020-05-14 11:49:34 -07003867 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3868 of INT64_MIN. This assumes two's compliment representation where
3869 INT64_MIN is one increment farther from 0 than INT64_MAX.
3870 Trying to write -INT64_MIN doesn't work to get this because the
3871 compiler tries to work with an int64_t which can't represent
3872 -INT64_MIN.
3873 */
3874 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3875
3876 // Error out if too large
3877 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003878 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3879 }
3880
3881 // Casts are safe because of checks above
3882 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3883
3884 return QCBOR_SUCCESS;
3885}
3886
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003887
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003888/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003889 Compute value with signed mantissa and unsigned result. Works with
3890 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003891 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003892static inline QCBORError ExponentitateNU(int64_t nMantissa,
3893 int64_t nExponent,
3894 uint64_t *puResult,
3895 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003896{
3897 if(nMantissa < 0) {
3898 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3899 }
3900
3901 // Cast to unsigned is OK because of check for negative
3902 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3903 // Exponentiation is straight forward
3904 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3905}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003906
3907
3908/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003909 Compute value with signed mantissa and unsigned result. Works with
3910 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003911 */
3912static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3913 int64_t nExponent,
3914 uint64_t *puResult,
3915 fExponentiator pfExp)
3916{
3917 return (*pfExp)(uMantissa, nExponent, puResult);
3918}
3919
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003920#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3921
3922
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003923
3924
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003925
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003926static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003927{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003928 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003929
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003930 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003931 const uint8_t *pByte = BigNum.ptr;
3932 size_t uLen = BigNum.len;
3933 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003934 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003935 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003937 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003938 }
3939
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003940 *pResult = uResult;
3941 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003942}
3943
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003944
Laurence Lundblade887add82020-05-17 05:50:34 -07003945static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003946{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003947 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003948}
3949
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003950
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003951static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003952{
3953 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003954 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3955 if(uError) {
3956 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957 }
3958 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3959 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003960 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003961}
3962
3963
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003964static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003965{
3966 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003967 /* The negative integer furthest from zero for a C int64_t is
3968 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3969 negative number in CBOR is computed as -n - 1 where n is the
3970 encoded integer, where n is what is in the variable BigNum. When
3971 converting BigNum to a uint64_t, the maximum value is thus
3972 INT64_MAX, so that when it -n - 1 is applied to it the result will
3973 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003974
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003975 -n - 1 <= INT64_MIN.
3976 -n - 1 <= -INT64_MAX - 1
3977 n <= INT64_MAX.
3978 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003979 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003980 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003981 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003982 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003983
3984 /// Now apply -n - 1. The cast is safe because
3985 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3986 // is the largest positive integer that an int64_t can
3987 // represent. */
3988 *pnResult = -(int64_t)uResult - 1;
3989
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003990 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991}
3992
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003993
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003994
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003995
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003996
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003997/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003998Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003999
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004000\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004001
Laurence Lundblade93d89472020-10-03 22:30:50 -07004002\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4003 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004004
4005\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4006
Laurence Lundblade93d89472020-10-03 22:30:50 -07004007\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4008 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004009*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004010static QCBORError
4011ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004012{
4013 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004014 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004016#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004018 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4019 http://www.cplusplus.com/reference/cmath/llround/
4020 */
4021 // Not interested in FE_INEXACT
4022 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004023 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4024 *pnValue = llround(pItem->val.dfnum);
4025 } else {
4026 *pnValue = lroundf(pItem->val.fnum);
4027 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004028 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4029 // llround() shouldn't result in divide by zero, but catch
4030 // it here in case it unexpectedly does. Don't try to
4031 // distinguish between the various exceptions because it seems
4032 // they vary by CPU, compiler and OS.
4033 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004034 }
4035 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004036 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004037 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004038#else
4039 return QCBOR_ERR_HW_FLOAT_DISABLED;
4040#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004041 break;
4042
4043 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004044 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004045 *pnValue = pItem->val.int64;
4046 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004047 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048 }
4049 break;
4050
4051 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004052 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004053 if(pItem->val.uint64 < INT64_MAX) {
4054 *pnValue = pItem->val.int64;
4055 } else {
4056 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4057 }
4058 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004059 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004060 }
4061 break;
4062
4063 default:
4064 return QCBOR_ERR_UNEXPECTED_TYPE;
4065 }
4066 return QCBOR_SUCCESS;
4067}
4068
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004069
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004070void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004073 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004074{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004075 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004076 return;
4077 }
4078
Laurence Lundbladee6430642020-03-14 21:15:44 -07004079 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004080 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4081 if(uError) {
4082 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083 return;
4084 }
4085
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004086 if(pItem) {
4087 *pItem = Item;
4088 }
4089
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004090 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091}
4092
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004093
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4095 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004096 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004097 int64_t *pnValue,
4098 QCBORItem *pItem)
4099{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004100 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004101 if(pMe->uLastError != QCBOR_SUCCESS) {
4102 return;
4103 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004104
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106}
4107
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004108
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004109void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4110 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112 int64_t *pnValue,
4113 QCBORItem *pItem)
4114{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004115 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004116 if(pMe->uLastError != QCBOR_SUCCESS) {
4117 return;
4118 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004120 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121}
4122
4123
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004124/*
4125 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004126
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004128
Laurence Lundblade93d89472020-10-03 22:30:50 -07004129 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4130 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004131
4132 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4133
Laurence Lundblade93d89472020-10-03 22:30:50 -07004134 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4135 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004136 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004137static QCBORError
4138Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004139{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140 switch(pItem->uDataType) {
4141
4142 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004143 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004144 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004145 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004146 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004147 }
4148 break;
4149
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004150 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004151 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004152 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004153 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004155 }
4156 break;
4157
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4159 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004161 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004162 pItem->val.expAndMantissa.nExponent,
4163 pnValue,
4164 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004165 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 }
4168 break;
4169
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004170 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004172 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004173 pItem->val.expAndMantissa.nExponent,
4174 pnValue,
4175 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004176 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004177 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004178 }
4179 break;
4180
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004181 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004182 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004183 int64_t nMantissa;
4184 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004185 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4186 if(uErr) {
4187 return uErr;
4188 }
4189 return ExponentiateNN(nMantissa,
4190 pItem->val.expAndMantissa.nExponent,
4191 pnValue,
4192 Exponentitate10);
4193 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004194 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004195 }
4196 break;
4197
4198 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004199 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004200 int64_t nMantissa;
4201 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004202 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4203 if(uErr) {
4204 return uErr;
4205 }
4206 return ExponentiateNN(nMantissa,
4207 pItem->val.expAndMantissa.nExponent,
4208 pnValue,
4209 Exponentitate10);
4210 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004211 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 }
4213 break;
4214
4215 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004217 int64_t nMantissa;
4218 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004219 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4220 if(uErr) {
4221 return uErr;
4222 }
4223 return ExponentiateNN(nMantissa,
4224 pItem->val.expAndMantissa.nExponent,
4225 pnValue,
4226 Exponentitate2);
4227 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004228 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004229 }
4230 break;
4231
4232 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004233 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004234 int64_t nMantissa;
4235 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004236 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4237 if(uErr) {
4238 return uErr;
4239 }
4240 return ExponentiateNN(nMantissa,
4241 pItem->val.expAndMantissa.nExponent,
4242 pnValue,
4243 Exponentitate2);
4244 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004246 }
4247 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004248#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4249
Laurence Lundbladee6430642020-03-14 21:15:44 -07004250
Laurence Lundbladec4537442020-04-14 18:53:22 -07004251 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004252 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004253}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004254
4255
Laurence Lundbladec4537442020-04-14 18:53:22 -07004256/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004257 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004258 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004259void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004260{
4261 QCBORItem Item;
4262
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004263 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004264
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004265 if(pMe->uLastError == QCBOR_SUCCESS) {
4266 // The above conversion succeeded
4267 return;
4268 }
4269
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004270 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004271 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004272 return;
4273 }
4274
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004275 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004276}
4277
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004278
4279/*
4280Public function, see header qcbor/qcbor_decode.h file
4281*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004282void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4283 int64_t nLabel,
4284 uint32_t uConvertTypes,
4285 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004286{
4287 QCBORItem Item;
4288
Laurence Lundblade93d89472020-10-03 22:30:50 -07004289 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4290 nLabel,
4291 uConvertTypes,
4292 pnValue,
4293 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004294
4295 if(pMe->uLastError == QCBOR_SUCCESS) {
4296 // The above conversion succeeded
4297 return;
4298 }
4299
4300 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4301 // The above conversion failed in a way that code below can't correct
4302 return;
4303 }
4304
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004305 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004306}
4307
4308
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004309/*
4310Public function, see header qcbor/qcbor_decode.h file
4311*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004312void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4313 const char *szLabel,
4314 uint32_t uConvertTypes,
4315 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004316{
4317 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004318 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4319 szLabel,
4320 uConvertTypes,
4321 pnValue,
4322 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004323
4324 if(pMe->uLastError == QCBOR_SUCCESS) {
4325 // The above conversion succeeded
4326 return;
4327 }
4328
4329 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4330 // The above conversion failed in a way that code below can't correct
4331 return;
4332 }
4333
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004335}
4336
4337
Laurence Lundblade93d89472020-10-03 22:30:50 -07004338static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004339{
4340 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004341 case QCBOR_TYPE_DOUBLE:
4342 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004343#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004344 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004345 // Can't use llround here because it will not convert values
4346 // greater than INT64_MAX and less than UINT64_MAX that
4347 // need to be converted so it is more complicated.
4348 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4349 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4350 if(isnan(pItem->val.dfnum)) {
4351 return QCBOR_ERR_FLOAT_EXCEPTION;
4352 } else if(pItem->val.dfnum < 0) {
4353 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4354 } else {
4355 double dRounded = round(pItem->val.dfnum);
4356 // See discussion in DecodeDateEpoch() for
4357 // explanation of - 0x7ff
4358 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4359 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4360 }
4361 *puValue = (uint64_t)dRounded;
4362 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004363 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004364 if(isnan(pItem->val.fnum)) {
4365 return QCBOR_ERR_FLOAT_EXCEPTION;
4366 } else if(pItem->val.fnum < 0) {
4367 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4368 } else {
4369 float fRounded = roundf(pItem->val.fnum);
4370 // See discussion in DecodeDateEpoch() for
4371 // explanation of - 0x7ff
4372 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4373 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4374 }
4375 *puValue = (uint64_t)fRounded;
4376 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004377 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004378 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4379 // round() and roundf() shouldn't result in exceptions here, but
4380 // catch them to be robust and thorough. Don't try to
4381 // distinguish between the various exceptions because it seems
4382 // they vary by CPU, compiler and OS.
4383 return QCBOR_ERR_FLOAT_EXCEPTION;
4384 }
4385
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004386 } else {
4387 return QCBOR_ERR_UNEXPECTED_TYPE;
4388 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004389#else
4390 return QCBOR_ERR_HW_FLOAT_DISABLED;
4391#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004392 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004393
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004394 case QCBOR_TYPE_INT64:
4395 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4396 if(pItem->val.int64 >= 0) {
4397 *puValue = (uint64_t)pItem->val.int64;
4398 } else {
4399 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4400 }
4401 } else {
4402 return QCBOR_ERR_UNEXPECTED_TYPE;
4403 }
4404 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004406 case QCBOR_TYPE_UINT64:
4407 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4408 *puValue = pItem->val.uint64;
4409 } else {
4410 return QCBOR_ERR_UNEXPECTED_TYPE;
4411 }
4412 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004414 default:
4415 return QCBOR_ERR_UNEXPECTED_TYPE;
4416 }
4417
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418 return QCBOR_SUCCESS;
4419}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004420
4421
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004422void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004425 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004426{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004427 if(pMe->uLastError != QCBOR_SUCCESS) {
4428 return;
4429 }
4430
Laurence Lundbladec4537442020-04-14 18:53:22 -07004431 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004432
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004433 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4434 if(uError) {
4435 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004436 return;
4437 }
4438
Laurence Lundbladea826c502020-05-10 21:07:00 -07004439 if(pItem) {
4440 *pItem = Item;
4441 }
4442
Laurence Lundblade93d89472020-10-03 22:30:50 -07004443 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004444}
4445
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004446
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004447void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004448 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004449 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004450 uint64_t *puValue,
4451 QCBORItem *pItem)
4452{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004453 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004454 if(pMe->uLastError != QCBOR_SUCCESS) {
4455 return;
4456 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457
Laurence Lundblade93d89472020-10-03 22:30:50 -07004458 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459}
4460
4461
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004462void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004463 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004464 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004465 uint64_t *puValue,
4466 QCBORItem *pItem)
4467{
4468 if(pMe->uLastError != QCBOR_SUCCESS) {
4469 return;
4470 }
4471
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004472 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004473 if(pMe->uLastError != QCBOR_SUCCESS) {
4474 return;
4475 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476
Laurence Lundblade93d89472020-10-03 22:30:50 -07004477 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004478}
4479
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004480
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004481
Laurence Lundblade93d89472020-10-03 22:30:50 -07004482static QCBORError
4483UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004485 switch(pItem->uDataType) {
4486
4487 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004489 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4490 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004492 }
4493 break;
4494
4495 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004496 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4498 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004500 }
4501 break;
4502
4503#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4504
4505 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004506 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004508 pItem->val.expAndMantissa.nExponent,
4509 puValue,
4510 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004511 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004512 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004513 }
4514 break;
4515
4516 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004517 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004518 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4519 pItem->val.expAndMantissa.nExponent,
4520 puValue,
4521 Exponentitate2);
4522 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004523 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524 }
4525 break;
4526
4527 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004530 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004531 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004532 if(uErr != QCBOR_SUCCESS) {
4533 return uErr;
4534 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004535 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004536 pItem->val.expAndMantissa.nExponent,
4537 puValue,
4538 Exponentitate10);
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_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004545 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
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 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004553 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004554 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004555 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004556 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557 if(uErr != QCBOR_SUCCESS) {
4558 return uErr;
4559 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004560 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561 pItem->val.expAndMantissa.nExponent,
4562 puValue,
4563 Exponentitate2);
4564 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004565 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004566 }
4567 break;
4568
4569 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004570 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4572 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004573 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004574 }
4575 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004576#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004577 default:
4578 return QCBOR_ERR_UNEXPECTED_TYPE;
4579 }
4580}
4581
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004582
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004583/*
4584 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004585 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004586void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004587{
4588 QCBORItem Item;
4589
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004591
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004592 if(pMe->uLastError == QCBOR_SUCCESS) {
4593 // The above conversion succeeded
4594 return;
4595 }
4596
4597 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4598 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004599 return;
4600 }
4601
Laurence Lundblade93d89472020-10-03 22:30:50 -07004602 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004603}
4604
Laurence Lundbladec4537442020-04-14 18:53:22 -07004605
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004606/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004607 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004609void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004610 int64_t nLabel,
4611 uint32_t uConvertTypes,
4612 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613{
4614 QCBORItem Item;
4615
Laurence Lundblade93d89472020-10-03 22:30:50 -07004616 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4617 nLabel,
4618 uConvertTypes,
4619 puValue,
4620 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004621
4622 if(pMe->uLastError == QCBOR_SUCCESS) {
4623 // The above conversion succeeded
4624 return;
4625 }
4626
4627 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4628 // The above conversion failed in a way that code below can't correct
4629 return;
4630 }
4631
Laurence Lundblade93d89472020-10-03 22:30:50 -07004632 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633}
4634
4635
4636/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004637 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004638*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004639void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004640 const char *szLabel,
4641 uint32_t uConvertTypes,
4642 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004643{
4644 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004645 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4646 szLabel,
4647 uConvertTypes,
4648 puValue,
4649 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004650
4651 if(pMe->uLastError == QCBOR_SUCCESS) {
4652 // The above conversion succeeded
4653 return;
4654 }
4655
4656 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4657 // The above conversion failed in a way that code below can't correct
4658 return;
4659 }
4660
Laurence Lundblade93d89472020-10-03 22:30:50 -07004661 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004662}
4663
4664
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004665
4666
Laurence Lundblade9b334962020-08-27 10:55:53 -07004667static QCBORError ConvertDouble(const QCBORItem *pItem,
4668 uint32_t uConvertTypes,
4669 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670{
4671 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004672 case QCBOR_TYPE_FLOAT:
4673#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4674 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4675 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004676 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004677 *pdValue = (double)pItem->val.fnum;
4678 } else {
4679 return QCBOR_ERR_UNEXPECTED_TYPE;
4680 }
4681 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004682#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004683 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004684#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004685 break;
4686
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004687 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004688 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4689 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690 *pdValue = pItem->val.dfnum;
4691 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004692 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004693 }
4694 }
4695 break;
4696
4697 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004698#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004699 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004700 // A simple cast seems to do the job with no worry of exceptions.
4701 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004702 *pdValue = (double)pItem->val.int64;
4703
4704 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004705 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004706 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004707#else
4708 return QCBOR_ERR_HW_FLOAT_DISABLED;
4709#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004710 break;
4711
4712 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004713#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004715 // A simple cast seems to do the job with no worry of exceptions.
4716 // There will be precision loss for some values.
4717 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004719 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720 }
4721 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004722#else
4723 return QCBOR_ERR_HW_FLOAT_DISABLED;
4724#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004725
4726 default:
4727 return QCBOR_ERR_UNEXPECTED_TYPE;
4728 }
4729
4730 return QCBOR_SUCCESS;
4731}
4732
4733
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004734void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004736 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004737 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004738{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004739 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004740 return;
4741 }
4742
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004743 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004744
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004745 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004746 if(uError) {
4747 pMe->uLastError = (uint8_t)uError;
4748 return;
4749 }
4750
4751 if(pItem) {
4752 *pItem = Item;
4753 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004754
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004755 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004756}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004757
Laurence Lundbladec4537442020-04-14 18:53:22 -07004758
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004759void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4760 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004761 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004762 double *pdValue,
4763 QCBORItem *pItem)
4764{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004765 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004766 if(pMe->uLastError != QCBOR_SUCCESS) {
4767 return;
4768 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004770 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004771}
4772
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004773
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4775 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004776 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004777 double *pdValue,
4778 QCBORItem *pItem)
4779{
4780 if(pMe->uLastError != QCBOR_SUCCESS) {
4781 return;
4782 }
4783
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004784 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004785 if(pMe->uLastError != QCBOR_SUCCESS) {
4786 return;
4787 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004788
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790}
4791
4792
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004793#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004794static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4795{
4796 double dResult;
4797
4798 dResult = 0.0;
4799 const uint8_t *pByte = BigNum.ptr;
4800 size_t uLen = BigNum.len;
4801 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004802 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004803 while(uLen--) {
4804 dResult = (dResult * 256.0) + (double)*pByte++;
4805 }
4806
4807 return dResult;
4808}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004809#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4810
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004811
Laurence Lundblade93d89472020-10-03 22:30:50 -07004812static QCBORError
4813DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004814{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004815#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004816 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004817 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4818
4819 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004821
4822#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004824 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004825 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4827 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4828 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004829 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 }
4831 break;
4832
4833 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004834 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004835 // Underflow gives 0, overflow gives infinity
4836 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4837 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004838 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004839 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 }
4841 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004842#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004843
4844 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4847 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004848 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849 }
4850 break;
4851
4852 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004853 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004854 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004855 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004856 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004857 }
4858 break;
4859
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004860#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4864 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4865 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 }
4868 break;
4869
4870 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4873 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4874 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876 }
4877 break;
4878
4879 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004880 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4882 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4883 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004884 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885 }
4886 break;
4887
4888 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004889 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004890 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4892 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004893 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004894 }
4895 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004896#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4897
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004898 default:
4899 return QCBOR_ERR_UNEXPECTED_TYPE;
4900 }
4901
4902 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004903
4904#else
4905 (void)pItem;
4906 (void)uConvertTypes;
4907 (void)pdValue;
4908 return QCBOR_ERR_HW_FLOAT_DISABLED;
4909#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4910
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004911}
4912
4913
4914/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004915 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004916*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004917void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4918 uint32_t uConvertTypes,
4919 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004920{
4921
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004922 QCBORItem Item;
4923
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004924 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004925
4926 if(pMe->uLastError == QCBOR_SUCCESS) {
4927 // The above conversion succeeded
4928 return;
4929 }
4930
4931 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4932 // The above conversion failed in a way that code below can't correct
4933 return;
4934 }
4935
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004936 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004937}
4938
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939
4940/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004941 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004942*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004943void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4944 int64_t nLabel,
4945 uint32_t uConvertTypes,
4946 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004947{
4948 QCBORItem Item;
4949
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004950 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004951
4952 if(pMe->uLastError == QCBOR_SUCCESS) {
4953 // The above conversion succeeded
4954 return;
4955 }
4956
4957 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4958 // The above conversion failed in a way that code below can't correct
4959 return;
4960 }
4961
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004962 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963}
4964
4965
4966/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004967 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004968*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004969void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4970 const char *szLabel,
4971 uint32_t uConvertTypes,
4972 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973{
4974 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004975 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004976
4977 if(pMe->uLastError == QCBOR_SUCCESS) {
4978 // The above conversion succeeded
4979 return;
4980 }
4981
4982 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4983 // The above conversion failed in a way that code below can't correct
4984 return;
4985 }
4986
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004987 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004988}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004989
4990
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004991
4992
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004993#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004994static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4995{
4996 while((uInt & 0xff00000000000000UL) == 0) {
4997 uInt = uInt << 8;
4998 };
4999
5000 UsefulOutBuf UOB;
5001
5002 UsefulOutBuf_Init(&UOB, Buffer);
5003
5004 while(uInt) {
5005 const uint64_t xx = uInt & 0xff00000000000000UL;
5006 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5007 uInt = uInt << 8;
5008 (void)xx;
5009 }
5010
5011 return UsefulOutBuf_OutUBuf(&UOB);
5012}
5013
5014
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005015static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5016 TagSpecification TagSpec,
5017 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005018{
5019 QCBORError uErr;
5020 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005021 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005022 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005023 if(uErr != QCBOR_SUCCESS) {
5024 goto Done;
5025 }
5026
5027 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5028 break; // Successful exit. Moving on to finish decoding.
5029 }
5030
5031 // The item is an array, which means an undecoded
5032 // mantissa and exponent, so decode it. It will then
5033 // have a different type and exit the loop if.
5034 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5035 if(uErr != QCBOR_SUCCESS) {
5036 goto Done;
5037 }
5038
5039 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005040 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005041 }
5042Done:
5043 return uErr;
5044}
5045
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005046
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005048 TagSpecification TagSpec,
5049 QCBORItem *pItem,
5050 int64_t *pnMantissa,
5051 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005052{
5053 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005054
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005055 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005056 if(uErr != QCBOR_SUCCESS) {
5057 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005058 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005059
Laurence Lundblade9b334962020-08-27 10:55:53 -07005060 switch (pItem->uDataType) {
5061
5062 case QCBOR_TYPE_DECIMAL_FRACTION:
5063 case QCBOR_TYPE_BIGFLOAT:
5064 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5065 *pnExponent = pItem->val.expAndMantissa.nExponent;
5066 break;
5067
5068 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5069 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5070 *pnExponent = pItem->val.expAndMantissa.nExponent;
5071 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5072 break;
5073
5074 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5075 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5076 *pnExponent = pItem->val.expAndMantissa.nExponent;
5077 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5078 break;
5079
5080 default:
5081 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5082 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005083
5084 Done:
5085 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005086}
5087
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005088
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005089static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005090 TagSpecification TagSpec,
5091 QCBORItem *pItem,
5092 UsefulBuf BufferForMantissa,
5093 UsefulBufC *pMantissa,
5094 bool *pbIsNegative,
5095 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005096{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005097 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005098
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005099 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005100 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005101 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005102 }
5103
5104 uint64_t uMantissa;
5105
5106 switch (pItem->uDataType) {
5107
5108 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005109 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005110 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5111 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5112 *pbIsNegative = false;
5113 } else {
5114 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5115 *pbIsNegative = true;
5116 }
5117 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5118 *pnExponent = pItem->val.expAndMantissa.nExponent;
5119 break;
5120
5121 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005122 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005123 *pnExponent = pItem->val.expAndMantissa.nExponent;
5124 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5125 *pbIsNegative = false;
5126 break;
5127
5128 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005129 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005130 *pnExponent = pItem->val.expAndMantissa.nExponent;
5131 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5132 *pbIsNegative = true;
5133 break;
5134
5135 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005136 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005137 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005138
5139Done:
5140 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005141}
5142
5143
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144/*
5145 Public function, see header qcbor/qcbor_decode.h file
5146*/
5147void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5148 uint8_t uTagRequirement,
5149 int64_t *pnMantissa,
5150 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005151{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005152 if(pMe->uLastError != QCBOR_SUCCESS) {
5153 return;
5154 }
5155
5156 QCBORItem Item;
5157 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5158 if(uError) {
5159 pMe->uLastError = (uint8_t)uError;
5160 return;
5161 }
5162
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005163 const TagSpecification TagSpec =
5164 {
5165 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005166 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5167 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5168 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005169 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005170
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005171 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005172}
5173
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005174
5175/*
5176 Public function, see header qcbor/qcbor_decode.h file
5177*/
5178void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005179 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005180 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005181 int64_t *pnMantissa,
5182 int64_t *pnExponent)
5183{
5184 if(pMe->uLastError != QCBOR_SUCCESS) {
5185 return;
5186 }
5187
5188 QCBORItem Item;
5189 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5190
5191 const TagSpecification TagSpec =
5192 {
5193 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005194 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5195 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5196 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005197 };
5198
5199 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5200}
5201
5202
5203/*
5204 Public function, see header qcbor/qcbor_decode.h file
5205*/
5206void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005207 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005208 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005209 int64_t *pnMantissa,
5210 int64_t *pnExponent)
5211{
5212 if(pMe->uLastError != QCBOR_SUCCESS) {
5213 return;
5214 }
5215
5216 QCBORItem Item;
5217 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5218
5219 const TagSpecification TagSpec =
5220 {
5221 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005222 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5223 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5224 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005225 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005226
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005227 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5228}
5229
5230
5231/*
5232 Public function, see header qcbor/qcbor_decode.h file
5233*/
5234void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5235 uint8_t uTagRequirement,
5236 UsefulBuf MantissaBuffer,
5237 UsefulBufC *pMantissa,
5238 bool *pbMantissaIsNegative,
5239 int64_t *pnExponent)
5240{
5241 if(pMe->uLastError != QCBOR_SUCCESS) {
5242 return;
5243 }
5244
5245 QCBORItem Item;
5246 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5247 if(uError) {
5248 pMe->uLastError = (uint8_t)uError;
5249 return;
5250 }
5251
5252 const TagSpecification TagSpec =
5253 {
5254 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005255 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5256 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5257 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005258 };
5259
Laurence Lundblade93d89472020-10-03 22:30:50 -07005260 ProcessMantissaAndExponentBig(pMe,
5261 TagSpec,
5262 &Item,
5263 MantissaBuffer,
5264 pMantissa,
5265 pbMantissaIsNegative,
5266 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005267}
5268
5269
5270/*
5271 Public function, see header qcbor/qcbor_decode.h file
5272*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005273void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005274 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005275 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005276 UsefulBuf BufferForMantissa,
5277 UsefulBufC *pMantissa,
5278 bool *pbIsNegative,
5279 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005280{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005281 if(pMe->uLastError != QCBOR_SUCCESS) {
5282 return;
5283 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005284
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005285 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005286 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005287 if(pMe->uLastError != QCBOR_SUCCESS) {
5288 return;
5289 }
5290
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005291 const TagSpecification TagSpec =
5292 {
5293 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005294 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5295 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5296 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005297 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005298
Laurence Lundblade93d89472020-10-03 22:30:50 -07005299 ProcessMantissaAndExponentBig(pMe,
5300 TagSpec,
5301 &Item,
5302 BufferForMantissa,
5303 pMantissa,
5304 pbIsNegative,
5305 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005306}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005307
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005308
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005309/*
5310 Public function, see header qcbor/qcbor_decode.h file
5311*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005312void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005313 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005314 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005315 UsefulBuf BufferForMantissa,
5316 UsefulBufC *pMantissa,
5317 bool *pbIsNegative,
5318 int64_t *pnExponent)
5319{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005320 if(pMe->uLastError != QCBOR_SUCCESS) {
5321 return;
5322 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005323
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005324 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005325 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5326 if(pMe->uLastError != QCBOR_SUCCESS) {
5327 return;
5328 }
5329
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005330 const TagSpecification TagSpec =
5331 {
5332 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005333 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5334 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5335 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005336 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005337
5338 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5339}
5340
5341
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005342/*
5343 Public function, see header qcbor/qcbor_decode.h file
5344*/
5345void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5346 uint8_t uTagRequirement,
5347 int64_t *pnMantissa,
5348 int64_t *pnExponent)
5349{
5350 if(pMe->uLastError != QCBOR_SUCCESS) {
5351 return;
5352 }
5353
5354 QCBORItem Item;
5355 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5356 if(uError) {
5357 pMe->uLastError = (uint8_t)uError;
5358 return;
5359 }
5360 const TagSpecification TagSpec =
5361 {
5362 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005363 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5364 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5365 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005366 };
5367
5368 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5369}
5370
5371
5372/*
5373 Public function, see header qcbor/qcbor_decode.h file
5374*/
5375void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005376 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005377 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005378 int64_t *pnMantissa,
5379 int64_t *pnExponent)
5380{
5381 if(pMe->uLastError != QCBOR_SUCCESS) {
5382 return;
5383 }
5384
5385 QCBORItem Item;
5386 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5387 if(pMe->uLastError != QCBOR_SUCCESS) {
5388 return;
5389 }
5390
5391 const TagSpecification TagSpec =
5392 {
5393 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005394 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5395 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5396 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005397 };
5398
5399 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5400}
5401
5402
5403/*
5404 Public function, see header qcbor/qcbor_decode.h file
5405*/
5406void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005407 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005408 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005409 int64_t *pnMantissa,
5410 int64_t *pnExponent)
5411{
5412 if(pMe->uLastError != QCBOR_SUCCESS) {
5413 return;
5414 }
5415
5416 QCBORItem Item;
5417 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5418 if(pMe->uLastError != QCBOR_SUCCESS) {
5419 return;
5420 }
5421
5422 const TagSpecification TagSpec =
5423 {
5424 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005425 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5426 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5427 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005428 };
5429
5430 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5431}
5432
5433
5434/*
5435 Public function, see header qcbor/qcbor_decode.h file
5436*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005437void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5438 uint8_t uTagRequirement,
5439 UsefulBuf MantissaBuffer,
5440 UsefulBufC *pMantissa,
5441 bool *pbMantissaIsNegative,
5442 int64_t *pnExponent)
5443{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005444 if(pMe->uLastError != QCBOR_SUCCESS) {
5445 return;
5446 }
5447
5448 QCBORItem Item;
5449 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5450 if(uError) {
5451 pMe->uLastError = (uint8_t)uError;
5452 return;
5453 }
5454
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005455 const TagSpecification TagSpec =
5456 {
5457 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005458 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5459 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5460 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005461 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005462
5463 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005464}
5465
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005466
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005467/*
5468 Public function, see header qcbor/qcbor_decode.h file
5469*/
5470void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005471 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005472 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005473 UsefulBuf BufferForMantissa,
5474 UsefulBufC *pMantissa,
5475 bool *pbIsNegative,
5476 int64_t *pnExponent)
5477{
5478 if(pMe->uLastError != QCBOR_SUCCESS) {
5479 return;
5480 }
5481
5482 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005483 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5484 if(pMe->uLastError != QCBOR_SUCCESS) {
5485 return;
5486 }
5487
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488 const TagSpecification TagSpec =
5489 {
5490 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005491 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5492 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5493 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005494 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005495
Laurence Lundblade93d89472020-10-03 22:30:50 -07005496 ProcessMantissaAndExponentBig(pMe,
5497 TagSpec,
5498 &Item,
5499 BufferForMantissa,
5500 pMantissa,
5501 pbIsNegative,
5502 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005503}
5504
5505
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005506/*
5507 Public function, see header qcbor/qcbor_decode.h file
5508*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005509void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005510 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005511 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005512 UsefulBuf BufferForMantissa,
5513 UsefulBufC *pMantissa,
5514 bool *pbIsNegative,
5515 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005516{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005517 if(pMe->uLastError != QCBOR_SUCCESS) {
5518 return;
5519 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005520
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005521 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005522 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5523 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005524 return;
5525 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005526
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005527 const TagSpecification TagSpec =
5528 {
5529 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005530 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5531 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5532 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005533 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005534
Laurence Lundblade93d89472020-10-03 22:30:50 -07005535 ProcessMantissaAndExponentBig(pMe,
5536 TagSpec,
5537 &Item,
5538 BufferForMantissa,
5539 pMantissa,
5540 pbIsNegative,
5541 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005542}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005543
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005544#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */