blob: 25f6cb946ae17ae1b88a460bb13f5d27a7f6e2f6 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade6474c982020-12-26 22:14:34 -080036#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070037
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade53b945a2020-12-27 02:05:01 -080039
Laurence Lundblade6474c982020-12-26 22:14:34 -080040#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
Laurence Lundblade53b945a2020-12-27 02:05:01 -080044
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080045#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade6474c982020-12-26 22:14:34 -080050 * This casts away the const-ness of a pointer, usually so it can be
51 * freed or realloced.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053052 */
53#define UNCONST_POINTER(ptr) ((void *)(ptr))
54
Laurence Lundbladea9489f82020-09-12 13:50:56 -070055#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
Laurence Lundblade6474c982020-12-26 22:14:34 -080058
59
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070060static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070061QCBORItem_IsMapOrArray(const QCBORItem *pMe)
62{
63 const uint8_t uDataType = pMe->uDataType;
64 return uDataType == QCBOR_TYPE_MAP ||
65 uDataType == QCBOR_TYPE_ARRAY ||
66 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
67}
68
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070069static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070070QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != 0) {
77 return false;
78 }
79 return true;
80}
81
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070082static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070083QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
84{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080085#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 if(!QCBORItem_IsMapOrArray(pMe)){
87 return false;
88 }
89
90 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
91 return false;
92 }
93 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080094#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
95 (void)pMe;
96 return false;
97#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070098}
99
100
Laurence Lundbladeee851742020-01-08 08:37:05 -0800101/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700102 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800103 ===========================================================================*/
104
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700105/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800106 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
107 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700108 */
109
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700111static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700112DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800115 /* Limit in DecodeNesting_Descend against more than
116 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700118 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119}
120
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700121
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700122static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700123DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800126 /* Limit in DecodeNesting_Descend against more than
127 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700128 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700129 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700130}
131
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700132
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700133static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700134DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700135{
136 return pNesting->pCurrentBounded->u.ma.uStartOffset;
137}
138
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700139
Laurence Lundblade085d7952020-07-24 10:26:30 -0700140static inline bool
141DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
142{
143 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
144 return true;
145 } else {
146 return false;
147 }
148}
149
150
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700151static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700155 return true;
156 } else {
157 return false;
158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159}
160
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700161
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700162static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700163DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164{
165 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800166 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return false;
168 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800169
170#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700171 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade6474c982020-12-26 22:14:34 -0800178 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700179 return true;
180}
181
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700182static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700183DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700184{
185 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800186 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700193static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
196 return true;
197 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700198 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700199 return true;
200 }
201 return false;
202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700205static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800209 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
210 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
211 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700214
215 if(bIsEmpty) {
216 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
217 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218}
219
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700220
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700221static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700223 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224}
225
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700226
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700227static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229{
230 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800231 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return false;
233 }
234 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800235 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700238 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800242 /* Works for both definite and indefinite length maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800243 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
244 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800248 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700249 return true;
250}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700253static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700254DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800256 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
258 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700259 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700260 return false;
261 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700262}
263
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700264
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700265static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700266DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
269 return true;
270 } else {
271 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700272 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273}
274
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700275
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700276static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700277DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700279 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700280 return false;
281 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282
283 if(pNesting->pCurrentBounded->uLevelType != uType) {
284 return false;
285 }
286
287 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700288}
289
Laurence Lundblade02625d42020-06-25 14:41:41 -0700290
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700291static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700292DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700293{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800294 /* Only call on a defnite length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700295 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700296}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700297
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700299static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
301{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800302 /* Only call on a defnite length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700303 pNesting->pCurrent->u.ma.uCountCursor++;
304}
305
306
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700307static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700308DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
309{
310 pNesting->pCurrent--;
311}
312
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313
314static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700315DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700316{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800317 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700318 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700319 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 }
321
Laurence Lundblade6474c982020-12-26 22:14:34 -0800322 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 pNesting->pCurrent++;
324
325 pNesting->pCurrent->uLevelType = uType;
326
327 return QCBOR_SUCCESS;
328}
329
330
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700331static inline QCBORError
Laurence Lundblade6474c982020-12-26 22:14:34 -0800332DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
333 bool bIsEmpty,
334 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700335{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700336 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800337 * Should only be called on map/array.
338 *
339 * Have descended into this before this is called. The job here is
340 * just to mark it in bounded mode.
341 *
342 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800343 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
344 *
345 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800347 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700348 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349 }
350
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700351 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700352
353 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700354
355 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700356}
357
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700358
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700359static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 uint8_t uQCBORType,
362 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366 if(uCount == 0) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800367 /* Nothing to do for empty definite lenth arrays. They are just are
368 * effectively the same as an item that is not a map or array.
369 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
Laurence Lundblade6474c982020-12-26 22:14:34 -0800371 /* Empty indefinite length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade6474c982020-12-26 22:14:34 -0800374 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
376 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700377 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700381 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383 goto Done;
384 }
385
Laurence Lundblade6474c982020-12-26 22:14:34 -0800386 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700387 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
388 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389
390 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700391
392Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 return uError;;
394}
395
396
397static inline void
398DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
401}
402
403
404static inline void
405DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
406{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 pNesting->pCurrentBounded--;
409 if(DecodeNesting_IsCurrentBounded(pNesting)) {
410 break;
411 }
412 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413}
414
Laurence Lundblade6474c982020-12-26 22:14:34 -0800415
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416static inline void
417DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
418{
419 pNesting->pCurrent = pNesting->pCurrentBounded;
420}
421
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700422
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700423static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700425 uint32_t uEndOffset,
426 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700428 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700430 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432 goto Done;
433 }
434
Laurence Lundblade6474c982020-12-26 22:14:34 -0800435 /* Fill in the new byte string level */
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700436 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
437 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438
Laurence Lundblade6474c982020-12-26 22:14:34 -0800439 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700440 pNesting->pCurrentBounded = pNesting->pCurrent;
441
442Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443 return uError;;
444}
445
Laurence Lundbladed0304932020-06-27 10:59:38 -0700446
447static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700449{
450 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700451}
452
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700453
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700454static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
456{
457 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
458}
459
460
461static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
466 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467}
468
469
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700470static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800471DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
472 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700473{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700474 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700475 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800476 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700477}
478
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700479
Laurence Lundblade02625d42020-06-25 14:41:41 -0700480static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800481DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
482 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700483{
484 *pNesting = *pSave;
485}
486
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487
Laurence Lundblade02625d42020-06-25 14:41:41 -0700488static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700490{
491 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
492}
493
494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700496DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700497{
498 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
499}
500
501
Laurence Lundblade6474c982020-12-26 22:14:34 -0800502
503
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800504#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
507
508 The following four functions are pretty wrappers for invocation of
509 the string allocator supplied by the caller.
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800514StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515{
516 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
517}
518
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519// StringAllocator_Reallocate called with pMem NULL is
520// equal to StringAllocator_Allocate()
521static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800522StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 void *pMem,
524 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800530StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531{
532 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
533}
534
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800536StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537{
538 if(pMe->pfAllocator) {
539 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
540 }
541}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800542#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
544
Laurence Lundblade6474c982020-12-26 22:14:34 -0800545
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547/*===========================================================================
548 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800550 See qcbor/qcbor_decode.h for definition of the object
551 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800552 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800554 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556void QCBORDecode_Init(QCBORDecodeContext *me,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
560 memset(me, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800562 /* Don't bother with error check on decode mode. If a bad value is
563 * passed it will just act as if the default normal mode of 0 was set.
564 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700565 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700566 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700567 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700568 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700569 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570}
571
572
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800573#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
574
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700575/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800576 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
579 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800580 void *pAllocateContext,
581 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700582{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
584 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
585 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800587#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700588
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589
Laurence Lundblade6474c982020-12-26 22:14:34 -0800590
591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800593 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800595void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700597{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800598 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700599 (void)pMe;
600 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601}
602
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700603
Laurence Lundblade1c929722020-12-27 02:44:57 -0800604/**
605 * @brief Decode the CBOR head, the type and argument.
606 *
607 * @param[in] pUInBuf The input buffer to read from.
608 * @param[out] pnMajorType The decoded major type.
609 * @param[out] puArgument The decoded argument.
610 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
611 *
612 * @retval QCBOR_ERR_UNSUPPORTED
613 * @retval QCBOR_ERR_HIT_END
614 *
615 * This decodes the CBOR "head" that every CBOR data item has. See
616 * longer explaination of the head in documentation for
617 * QCBOREncode_EncodeHead().
618 *
619 * This does the network->host byte order conversion. The conversion
620 * here also results in the conversion for floats in addition to that
621 * for lengths, tags and integer values.
622 *
623 * The int type is preferred to uint8_t for some variables as this
624 * avoids integer promotions, can reduce code size and makes static
625 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800627static inline QCBORError
628DecodeHead(UsefulInputBuf *pUInBuf,
629 int *pnMajorType,
630 uint64_t *puArgument,
631 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800633 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundblade1c929722020-12-27 02:44:57 -0800635 /* Get the initial byte that every CBOR data item has and break it
636 * down. */
637 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 const int nTmpMajorType = nInitialByte >> 5;
639 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundblade1c929722020-12-27 02:44:57 -0800641 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800644 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800645 /* Need to get 1,2,4 or 8 additional argument bytes. Map
646 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
647 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800648 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundblade1c929722020-12-27 02:44:57 -0800650 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800651 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800653 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800654 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
655 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800657 /* The reserved and thus-far unused additional info values */
658 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 goto Done;
660 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800661 /* Less than 24, additional info is argument or 31, an
662 * indefinite length. No more bytes to get.
663 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800668 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 goto Done;
670 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671
Laurence Lundblade1c929722020-12-27 02:44:57 -0800672 /* All successful if arrived here. */
673 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800676 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800677
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800679 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680}
681
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682
Laurence Lundblade1c929722020-12-27 02:44:57 -0800683/**
684 * @brief Decode integer types, major types 0 and 1.
685 *
686 * @param[in] nMajorType The CBOR major type (0 or 1).
687 * @param[in] uArgument The argument from the head.
688 * @param[out] pDecodedItem The filled in decoded item.
689 *
690 * @retval QCBOR_ERR_INT_OVERFLOW
691 *
692 * Must only be called when major type is 0 or 1.
693 *
694 * CBOR doesn't explicitly specify two's compliment for integers but
695 * all CPUs use it these days and the test vectors in the RFC are
696 * so. All integers in the CBOR structure are positive and the major
697 * type indicates positive or negative. CBOR can express positive
698 * integers up to 2^x - 1 where x is the number of bits and negative
699 * integers down to 2^x. Note that negative numbers can be one more
700 * away from zero than positive. Stdint, as far as I can tell, uses
701 * two's compliment to represent negative integers.
702 *
703 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
704 * used carefully here, and in particular why it isn't used in the
705 * public interface. Also see
706 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
707 *
708 * Int is used for values that need less than 16-bits and would be
709 * subject to integer promotion and result in complaining from static
710 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700712static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800713DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800715 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800718 if (uArgument <= INT64_MAX) {
719 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800723 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800728 if(uArgument <= INT64_MAX) {
729 /* CBOR's representation of negative numbers lines up with
730 * the two-compliment representation. A negative integer has
731 * one more in range than a positive integer. INT64_MIN is
732 * equal to (-INT64_MAX) - 1.
733 */
734 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800736
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800738 /* C can't represent a negative integer in this range so it
739 * is an error.
740 */
741 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
743 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundblade1c929722020-12-27 02:44:57 -0800745 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746}
747
Laurence Lundblade1c929722020-12-27 02:44:57 -0800748
Laurence Lundblade38299092020-12-28 04:13:50 -0800749/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
751#error QCBOR_TYPE_FALSE macro value wrong
752#endif
753
754#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
755#error QCBOR_TYPE_TRUE macro value wrong
756#endif
757
758#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
759#error QCBOR_TYPE_NULL macro value wrong
760#endif
761
762#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
763#error QCBOR_TYPE_UNDEF macro value wrong
764#endif
765
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700766#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
767#error QCBOR_TYPE_BREAK macro value wrong
768#endif
769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
771#error QCBOR_TYPE_DOUBLE macro value wrong
772#endif
773
774#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
775#error QCBOR_TYPE_FLOAT macro value wrong
776#endif
777
Laurence Lundblade38299092020-12-28 04:13:50 -0800778
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700779/*
Laurence Lundblade38299092020-12-28 04:13:50 -0800780* @brief Decode type 7 -- true, false, floating-point, break...
781*
782* @param[in] nAdditionalInfo The lower five bits from the initial byte.
783* @param[in] uArgument The argument from the head.
784* @param[out] pDecodedItem The filled in decoded item.
785*
786* @retval QCBOR_ERR_HALF_PRECISION_DISABLED
787* @retval QCBOR_ERR_BAD_TYPE_7
788*/
Laurence Lundblade9b334962020-08-27 10:55:53 -0700789
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700790static inline QCBORError
Laurence Lundblade38299092020-12-28 04:13:50 -0800791DecodeSimple(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792{
Laurence Lundblade38299092020-12-28 04:13:50 -0800793 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundblade38299092020-12-28 04:13:50 -0800795 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
796 * checks above make sure uAdditionalInfo values line up with
797 * uDataType values. DecodeHead() never returns an AdditionalInfo
798 * > 0x1f so cast is safe.
799 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800802 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800803 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
804 * are caught before this is called.
805 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundblade38299092020-12-28 04:13:50 -0800807 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700808#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800809 /* Half-precision is returned as a double. The cast to
810 * uint16_t is safe because the encoded value was 16 bits. It
811 * was widened to 64 bits to be passed in here.
812 */
813 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700814 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800815#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800816 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800817#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700818 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800819 case SINGLE_PREC_FLOAT: /* 26 */
820 /* Single precision is normally returned as a double since
821 * double is widely supported, there is no loss of precision,
822 * it makes it easy for the caller in most cases and it can
823 * be converted back to single with no loss of precision
824 *
825 * The cast to uint32_t is safe because the encoded value was
826 * 32 bits. It was widened to 64 bits to be passed in here.
827 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700828 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800829 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700830#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800831 /* In the normal case, use HW to convert float to
832 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700833 pDecodedItem->val.dfnum = (double)f;
834 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800835#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800836 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700837 pDecodedItem->val.fnum = f;
838 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
839
Laurence Lundblade38299092020-12-28 04:13:50 -0800840 /* IEEE754_FloatToDouble() could be used here to return as
841 * a double, but it adds object code and most likely
842 * anyone disabling FLOAT HW use doesn't care about floats
843 * and wants to save object code.
844 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800845#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700846 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700847 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700848
Laurence Lundblade38299092020-12-28 04:13:50 -0800849 case DOUBLE_PREC_FLOAT: /* 27 */
850 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700851 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700852 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade38299092020-12-28 04:13:50 -0800854 case CBOR_SIMPLEV_FALSE: /* 20 */
855 case CBOR_SIMPLEV_TRUE: /* 21 */
856 case CBOR_SIMPLEV_NULL: /* 22 */
857 case CBOR_SIMPLEV_UNDEF: /* 23 */
858 case CBOR_SIMPLE_BREAK: /* 31 */
859 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800860
Laurence Lundblade38299092020-12-28 04:13:50 -0800861 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
862 if(uArgument <= CBOR_SIMPLE_BREAK) {
863 /* This takes out f8 00 ... f8 1f which should be encoded
864 * as e0 … f7
865 */
866 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 goto Done;
868 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800869 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundblade38299092020-12-28 04:13:50 -0800871 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800873 /* DecodeHead() will make uArgument equal to
874 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
875 * safe because the 2, 4 and 8 byte lengths of uNumber are in
876 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800877 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800878 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879 break;
880 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700882Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800883 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884}
885
886
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530888 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700889
890 @retval QCBOR_ERR_HIT_END
891
892 @retval QCBOR_ERR_STRING_ALLOCATE
893
894 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800896static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800897DecodeBytes(const QCBORInternalAllocator *pAllocator,
898 uint64_t uStrLen,
899 UsefulInputBuf *pUInBuf,
900 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700902 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800904 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
905 // This check makes the casts to size_t below safe.
906
907 // 4 bytes less than the largest sizeof() so this can be tested by
908 // putting a SIZE_MAX length in the CBOR test input (no one will
909 // care the limit on strings is 4 bytes shorter).
910 if(uStrLen > SIZE_MAX-4) {
911 nReturn = QCBOR_ERR_STRING_TOO_LONG;
912 goto Done;
913 }
914
915 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530916 if(UsefulBuf_IsNULLC(Bytes)) {
917 // Failed to get the bytes for this string item
918 nReturn = QCBOR_ERR_HIT_END;
919 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530921
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800922#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800923 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530924 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800925 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530926 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700927 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530928 goto Done;
929 }
930 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800932 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530933 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800934#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
935 (void)pAllocator;
936#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
937
938 // Normal case with no string allocator
939 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530941Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942 return nReturn;
943}
944
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800946/* Map the CBOR major types for strings to the QCBOR types for strngs */
947static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
948{
949 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
950 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
951 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800953 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
954 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
955 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700956
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800957 return (uint8_t)(nCBORMajorType + 4);
958}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700959
960
Laurence Lundbladeee851742020-01-08 08:37:05 -0800961// Make sure the constants align as this is assumed by
962// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
964#error QCBOR_TYPE_ARRAY value not lined up with major type
965#endif
966#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
967#error QCBOR_TYPE_MAP value not lined up with major type
968#endif
969
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700970/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800971 This gets a single data item and decodes it including preceding
972 optional tagging. This does not deal with arrays and maps and nesting
973 except to decode the data item introducing them. Arrays and maps are
974 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800975
Laurence Lundbladeee851742020-01-08 08:37:05 -0800976 Errors detected here include: an array that is too long to decode,
977 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700978
979 @retval QCBOR_ERR_UNSUPPORTED
980
981 @retval QCBOR_ERR_HIT_END
982
983 @retval QCBOR_ERR_INT_OVERFLOW
984
985 @retval QCBOR_ERR_STRING_ALLOCATE
986
987 @retval QCBOR_ERR_STRING_TOO_LONG
988
989 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
990
991 @retval QCBOR_ERR_BAD_TYPE_7
992
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700993 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800994static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
995 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800996 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700997{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700998 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundbladeee851742020-01-08 08:37:05 -08001000 /*
1001 Get the major type and the number. Number could be length of more
1002 bytes or the value depending on the major type nAdditionalInfo is
1003 an encoding of the length of the uNumber and is needed to decode
1004 floats and doubles
1005 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001006 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001007 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001008 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001009
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001010 memset(pDecodedItem, 0, sizeof(QCBORItem));
1011
Laurence Lundblade1c929722020-12-27 02:44:57 -08001012 nReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladeee851742020-01-08 08:37:05 -08001014 // Error out here if we got into trouble on the type and number. The
1015 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001016 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 // At this point the major type and the value are valid. We've got
1021 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1024 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001025 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001026 nReturn = QCBOR_ERR_BAD_INT;
1027 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001028 nReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001029 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001031
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1033 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001034 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001035 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001036 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001038 nReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001039 }
1040 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1043 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1044 // Record the number of items in the array or map
Laurence Lundblade1c929722020-12-27 02:44:57 -08001045 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001046 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047 goto Done;
1048 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001049 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001050#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001051 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001052#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1053 nReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1054 break;
1055#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001056 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001057 // type conversion OK because of check above
Laurence Lundblade1c929722020-12-27 02:44:57 -08001058 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001060 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001061 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001062 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001066 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001067 nReturn = QCBOR_ERR_BAD_INT;
1068 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001069 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001070 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001071 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundbladeee851742020-01-08 08:37:05 -08001074 case CBOR_MAJOR_TYPE_SIMPLE:
1075 // Major type 7, float, double, true, false, null...
Laurence Lundblade1c929722020-12-27 02:44:57 -08001076 nReturn = DecodeSimple(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001077 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundbladeee851742020-01-08 08:37:05 -08001079 default:
1080 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 nReturn = QCBOR_ERR_UNSUPPORTED;
1082 break;
1083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085Done:
1086 return nReturn;
1087}
1088
1089
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001090/**
1091 * @brief Process indefinite length strings
1092 *
1093 * @param[in] pMe Decoder context
1094 * @param[in,out] pDecodedItem The decoded item that work is done on.
1095 *
1096 * @retval QCBOR_ERR_UNSUPPORTED
1097 * @retval QCBOR_ERR_HIT_END
1098 * @retval QCBOR_ERR_INT_OVERFLOW
1099 * @retval QCBOR_ERR_STRING_ALLOCATE
1100 * @retval QCBOR_ERR_STRING_TOO_LONG
1101 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1102 * @retval QCBOR_ERR_BAD_TYPE_7
1103 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1104 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1105 *
1106 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1107 *
1108 * If it is, this loops getting the subsequent chunks that make up the
1109 * string. The string allocator is used to make a contiguous buffer for
1110 * the chunks. When this completes @c pDecodedItem contains the
1111 * put-together string.
1112 *
1113 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001114 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001115static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001116GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001118 /* Aproximate stack usage
1119 * 64-bit 32-bit
1120 * local vars 32 16
1121 * 2 UsefulBufs 32 16
1122 * QCBORItem 56 52
1123 * TOTAL 120 74
1124 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001125
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001126 /* The string allocator is used here for two purposes: 1)
1127 * coalescing the chunks of an indefinite length string, 2)
1128 * allocating storage for every string returned.
1129 *
1130 * The first use is below in this function. Indefinite length
1131 * strings cannot be processed at all without a string allocator.
1132 *
1133 * The second used is in DecodeBytes() which is called by
1134 * GetNext_Item() below. This second use unneccessary for most use
1135 * and only happens when requested in the call to
1136 * QCBORDecode_SetMemPool(). If the second use not requested then
1137 * NULL is passed for the string allocator to GetNext_Item().
1138 *
1139 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1140 * allocator altogether and thus both of these uses. It reduced the
1141 * decoder object code by about 400 bytes.
1142 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001143 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001144
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001145#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001146 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001147
1148 if(pMe->StringAllocator.pfAllocator) {
1149 pAllocator = &(pMe->StringAllocator);
1150 if(pMe->bStringAllocateAll) {
1151 pAllocatorForGetNext = pAllocator;
1152 }
1153 }
1154#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1155
1156 QCBORError uReturn;
1157 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1158 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159 goto Done;
1160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001161
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001162 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001163 const uint8_t uStringType = pDecodedItem->uDataType;
1164 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001165 goto Done;
1166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001168 /* Is this a string with an indefinite length? */
1169 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1170 goto Done;
1171 }
1172
1173#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1174 /* Can't do indefinite length strings without a string allocator */
1175 if(pAllocator == NULL) {
1176 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1177 goto Done;
1178 }
1179
1180 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001181 UsefulBufC FullString = NULLUsefulBufC;
1182
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001183 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001185 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001186 /* Pass a NULL string allocator to GetNext_Item() because the
1187 * individual string chunks in an indefinite length should not
1188 * be allocated. They are always copied in the the contiguous
1189 * buffer allocated here.
1190 */
1191 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1192 if(uReturn) {
1193 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001195
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001196 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001197 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001199 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301200 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001201 break;
1202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204 /* All chunks must be of the same type, the type of the item
1205 * that introduces the indefinite length string. This also
1206 * catches errors where the chunk is not a string at all and an
1207 * indefinite length string inside an indefinite length string.
1208 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001209 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001210 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1211 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001212 break;
1213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001214
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001215 /* The first time throurgh FullString.ptr is NULL and this is
1216 * equivalent to StringAllocator_Allocate(). Subsequently it is
1217 * not NULL and a reallocation happens.
1218 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001219 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1220 UNCONST_POINTER(FullString.ptr),
1221 FullString.len + StringChunkItem.val.string.len);
1222
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001223 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001224 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001225 break;
1226 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001227
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001228 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001229 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001230 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001231
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001232 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1233 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001234 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001235 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1237 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1238#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001239
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001240Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001241 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001242}
1243
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001244
Laurence Lundblade9b334962020-08-27 10:55:53 -07001245static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001246 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001247 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001248 } else if(uTagVal == CBOR_TAG_INVALID16) {
1249 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001250 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001251 // This won't be negative because of code below in GetNext_TaggedItem()
1252 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1253 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001254 }
1255}
1256
Laurence Lundblade9b334962020-08-27 10:55:53 -07001257
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001258/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001259 Gets all optional tag data items preceding a data item that is not an
1260 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261
1262 @retval QCBOR_ERR_UNSUPPORTED
1263
1264 @retval QCBOR_ERR_HIT_END
1265
1266 @retval QCBOR_ERR_INT_OVERFLOW
1267
1268 @retval QCBOR_ERR_STRING_ALLOCATE
1269
1270 @retval QCBOR_ERR_STRING_TOO_LONG
1271
1272 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1273
1274 @retval QCBOR_ERR_BAD_TYPE_7
1275
1276 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1277
1278 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1279
1280 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001281 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001282static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001283GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001284{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001285 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1286 CBOR_TAG_INVALID16,
1287 CBOR_TAG_INVALID16,
1288 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001289
Laurence Lundblade9b334962020-08-27 10:55:53 -07001290 QCBORError uReturn = QCBOR_SUCCESS;
1291
Laurence Lundblade59289e52019-12-30 13:44:37 -08001292 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001293 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001294 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1295 if(uErr != QCBOR_SUCCESS) {
1296 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001297 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001298 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001299
Laurence Lundblade9b334962020-08-27 10:55:53 -07001300 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001301 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001303 break;
1304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundblade9b334962020-08-27 10:55:53 -07001306 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1307 // No room in the tag list
1308 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1309 // Continue on to get all tags on this item even though
1310 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001311 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001312 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001313 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001314 // Slide tags over one in the array to make room at index 0
1315 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1316 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001318
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001319 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001320 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001321 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001322 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001323 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001324 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001325 break;
1326 }
1327 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1328 break;
1329 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001330 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001331 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1332 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001333 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1334 // Continue on to get all tags on this item even though
1335 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001336 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001337 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001338 }
1339
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001340 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001341 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001342 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001343
1344 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001345 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001346 }
1347 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001348
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001349Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001350 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001351}
1352
1353
1354/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001355 This layer takes care of map entries. It combines the label and data
1356 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001357
1358 @retval QCBOR_ERR_UNSUPPORTED
1359
1360 @retval QCBOR_ERR_HIT_END
1361
1362 @retval QCBOR_ERR_INT_OVERFLOW
1363
1364 @retval QCBOR_ERR_STRING_ALLOCATE
1365
1366 @retval QCBOR_ERR_STRING_TOO_LONG
1367
1368 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1369
1370 @retval QCBOR_ERR_BAD_TYPE_7
1371
1372 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1373
1374 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1375
1376 @retval QCBOR_ERR_TOO_MANY_TAGS
1377
1378 @retval QCBOR_ERR_MAP_LABEL_TYPE
1379
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001380 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001381 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001382static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001383GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001384{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001385 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001386 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001387 if(nReturn)
1388 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001389
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001390 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001391 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001392 goto Done;
1393 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001394
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001395 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1396 // In a map and caller wants maps decoded, not treated as arrays
1397
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001398 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001399 // If in a map and the right decoding mode, get the label
1400
Laurence Lundbladeee851742020-01-08 08:37:05 -08001401 // Save label in pDecodedItem and get the next which will
1402 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001403 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001404 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001405 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001406 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001407 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001408
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301409 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001410
1411 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1412 // strings are always good labels
1413 pDecodedItem->label.string = LabelItem.val.string;
1414 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1415 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001416 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001417 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1418 goto Done;
1419 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1420 pDecodedItem->label.int64 = LabelItem.val.int64;
1421 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1422 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1423 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1424 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1425 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1426 pDecodedItem->label.string = LabelItem.val.string;
1427 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1428 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1429 } else {
1430 // label is not an int or a string. It is an arrray
1431 // or a float or such and this implementation doesn't handle that.
1432 // Also, tags on labels are ignored.
1433 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1434 goto Done;
1435 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001436 }
1437 } else {
1438 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001439 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001440 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001441 goto Done;
1442 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001443 // Decoding a map as an array
1444 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001445 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1446 // Cast is needed because of integer promotion
1447 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001448 }
1449 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001450
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001451Done:
1452 return nReturn;
1453}
1454
1455
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001456#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457/*
1458 See if next item is a CBOR break. If it is, it is consumed,
1459 if not it is not consumed.
1460*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001461static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001462NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1463{
1464 *pbNextIsBreak = false;
1465 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001466 QCBORItem Peek;
1467 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1468 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1469 if(uReturn != QCBOR_SUCCESS) {
1470 return uReturn;
1471 }
1472 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001473 // It is not a break, rewind so it can be processed normally.
1474 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001475 } else {
1476 *pbNextIsBreak = true;
1477 }
1478 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001479
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001480 return QCBOR_SUCCESS;
1481}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001482#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001483
1484
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001485/*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001486 * An item was just consumed, now figure out if it was the
1487 * end of an array/map map that can be closed out. That
1488 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001489*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001490static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001491{
1492 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001493
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001494 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1496
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001497 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1498 /* Nesting level is bstr-wrapped CBOR */
1499
1500 /* Ascent for bstr-wrapped CBOR is always by explicit call
1501 * so no further ascending can happen.
1502 */
1503 break;
1504
1505 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1506 /* Level is a definite-length array/map */
1507
1508 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001509 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1510 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001511 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001512 break;
1513 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001514 /* All items in a definite length array were consumed so it
1515 * is time to ascend one level. This happens below.
1516 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001517
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001518#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001519 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001520 /* Level is an indefinite-length array/map. */
1521
1522 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001523 bool bIsBreak = false;
1524 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1525 if(uReturn != QCBOR_SUCCESS) {
1526 goto Done;
1527 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001528
1529 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001530 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001531 break;
1532 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001533
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001534 /* It was a break in an indefinite length map / array so
1535 * it is time to ascend one level.
1536 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001537
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001538#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001539 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001540
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001541
1542 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001543
Laurence Lundblade93d89472020-10-03 22:30:50 -07001544 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001545 * QCBORDecode_ExitBoundedMode().
1546 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001547 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001548 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001549 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001550 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001551 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001552 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001553
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001554 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001555 break;
1556 }
1557
1558 /* Finally, actually ascend one level. */
1559 DecodeNesting_Ascend(&(pMe->nesting));
1560 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001561
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001562 uReturn = QCBOR_SUCCESS;
1563
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001564#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001565Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001566#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1567
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001568 return uReturn;
1569}
1570
1571
1572/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001573 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001574 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1575 indefinte length maps and arrays by looking at the item count or
1576 finding CBOR breaks. It detects the ends of the top-level sequence
1577 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001578
1579 @retval QCBOR_ERR_UNSUPPORTED X
1580
1581 @retval QCBOR_ERR_HIT_END
1582
1583 @retval QCBOR_ERR_INT_OVERFLOW X
1584
1585 @retval QCBOR_ERR_STRING_ALLOCATE
1586
1587 @retval QCBOR_ERR_STRING_TOO_LONG
1588
1589 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1590
1591 @retval QCBOR_ERR_BAD_TYPE_7 X
1592
1593 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1594
1595 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1596
1597 @retval QCBOR_ERR_TOO_MANY_TAGS
1598
1599 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1600
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001601 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001602
1603 @retval QCBOR_ERR_NO_MORE_ITEMS
1604
1605 @retval QCBOR_ERR_BAD_BREAK
1606
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001607 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001608static QCBORError
1609QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001610{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001611 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001612 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001613
Laurence Lundblade642282a2020-06-23 12:00:33 -07001614 /*
1615 If out of bytes to consume, it is either the end of the top-level
1616 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001617
Laurence Lundblade642282a2020-06-23 12:00:33 -07001618 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1619 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1620 CBOR is exited, the length is set back to the top-level's length
1621 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001622 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001623 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001625 goto Done;
1626 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001627
Laurence Lundblade642282a2020-06-23 12:00:33 -07001628 /*
1629 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001630 array. The check for a break ending indefinite length array is
1631 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001632 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001633 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001634 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001635 goto Done;
1636 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001637
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001638 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001639 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001640 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1641 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001642 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001643 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301644
Laurence Lundblade642282a2020-06-23 12:00:33 -07001645 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001646 Breaks ending arrays/maps are processed later in the call to
1647 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001648 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301649 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001650 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301651 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301652 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001653
Laurence Lundblade642282a2020-06-23 12:00:33 -07001654 /*
1655 Record the nesting level for this data item before processing any
1656 of decrementing and descending.
1657 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001658 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001659
Laurence Lundblade642282a2020-06-23 12:00:33 -07001660
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001661 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001662 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001663 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001664 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001665
Laurence Lundblade93d89472020-10-03 22:30:50 -07001666 Empty indefinite length maps and arrays are descended into, but
1667 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001668
1669 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001670 encloses them so a decrement needs to be done for them too, but
1671 that is done only when all the items in them have been
1672 processed, not when they are opened with the exception of an
1673 empty map or array.
1674 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001675 QCBORError uDescendErr;
1676 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001677 pDecodedItem->uDataType,
1678 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001679 if(uDescendErr != QCBOR_SUCCESS) {
1680 /* This error is probably a traversal error and it
1681 overrides the non-traversal error. */
1682 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001683 goto Done;
1684 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001685 }
1686
Laurence Lundblade02625d42020-06-25 14:41:41 -07001687 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1688 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1689 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001690 /*
1691 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001692 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001693 - An empty definite length map or array
1694 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001695
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001696 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001697 definite length map/array and break detection for an indefinite
1698 length map/array. If the end of the map/array was reached, then
1699 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001700 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001701 QCBORError uAscendErr;
1702 uAscendErr = NestLevelAscender(me, true);
1703 if(uAscendErr != QCBOR_SUCCESS) {
1704 /* This error is probably a traversal error and it
1705 overrides the non-traversal error. */
1706 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001707 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001708 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301709 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001710
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001711 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001712 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001713 Tell the caller what level is next. This tells them what
1714 maps/arrays were closed out and makes it possible for them to
1715 reconstruct the tree with just the information returned in
1716 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001717 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001718 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001719 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001720 pDecodedItem->uNextNestLevel = 0;
1721 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001722 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001723 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001724
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001725Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001726 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001727}
1728
Laurence Lundblade9b334962020-08-27 10:55:53 -07001729static void ShiftTags(QCBORItem *pDecodedItem)
1730{
1731 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1732 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1733 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1734 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1735}
1736
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001737
Laurence Lundblade9b334962020-08-27 10:55:53 -07001738
Laurence Lundblade59289e52019-12-30 13:44:37 -08001739/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001740 The epoch formatted date. Turns lots of different forms of encoding
1741 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001742 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001743static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001744{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001745 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746
1747 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1748
1749 switch (pDecodedItem->uDataType) {
1750
1751 case QCBOR_TYPE_INT64:
1752 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1753 break;
1754
1755 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001756 // This only happens for CBOR type 0 > INT64_MAX so it is
1757 // always an overflow.
1758 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1759 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001760 break;
1761
1762 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001763 case QCBOR_TYPE_FLOAT:
1764#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001765 {
1766 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001767 // conversion to an int64_t to be able to detect doubles that
1768 // are too large to fit into an int64_t. A double has 52
1769 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1770 // to a double actually causes a round up which is bad and
1771 // wrong for the comparison because it will allow conversion
1772 // of doubles that can't fit into a uint64_t. To remedy this
1773 // INT64_MAX - 0x7ff is used as the cutoff point because if
1774 // that value rounds up in conversion to double it will still
1775 // be less than INT64_MAX. 0x7ff is picked because it has 11
1776 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001777 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001778 // INT64_MAX seconds is on the order of 10 billion years, and
1779 // the earth is less than 5 billion years old, so for most
1780 // uses this conversion error won't occur even though doubles
1781 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001782 //
1783 // Without the 0x7ff there is a ~30 minute range of time
1784 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001785 // where this code would go wrong. Some compilers
1786 // will generate warnings or errors without the 0x7ff
1787 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001788 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1789 pDecodedItem->val.dfnum :
1790 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001791 if(isnan(d) ||
1792 d > (double)(INT64_MAX - 0x7ff) ||
1793 d < (double)(INT64_MIN + 0x7ff)) {
1794 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001795 goto Done;
1796 }
1797 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001798 pDecodedItem->val.epochDate.fSecondsFraction =
1799 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001801#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001802
Laurence Lundbladec7114722020-08-13 05:11:40 -07001803 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001804 goto Done;
1805
Laurence Lundblade9682a532020-06-06 18:33:04 -07001806#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807 break;
1808
1809 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001810 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001811 goto Done;
1812 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001813
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1815
1816Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001817 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001818}
1819
1820
1821#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1822/*
1823 Decode decimal fractions and big floats.
1824
1825 When called pDecodedItem must be the array that is tagged as a big
1826 float or decimal fraction, the array that has the two members, the
1827 exponent and mantissa.
1828
1829 This will fetch and decode the exponent and mantissa and put the
1830 result back into pDecodedItem.
1831 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001832static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1834{
1835 QCBORError nReturn;
1836
1837 // --- Make sure it is an array; track nesting level of members ---
1838 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1839 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1840 goto Done;
1841 }
1842
1843 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001844 // definite length arrays, but not for indefnite. Instead remember
1845 // the nesting level the two integers must be at, which is one
1846 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001847 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1848
1849 // --- Is it a decimal fraction or a bigfloat? ---
1850 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1851 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1852
1853 // --- Get the exponent ---
1854 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001855 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001856 if(nReturn != QCBOR_SUCCESS) {
1857 goto Done;
1858 }
1859 if(exponentItem.uNestingLevel != nNestLevel) {
1860 // Array is empty or a map/array encountered when expecting an int
1861 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1862 goto Done;
1863 }
1864 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1865 // Data arriving as an unsigned int < INT64_MAX has been converted
1866 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1867 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1868 // will be too large for this to handle and thus an error that will
1869 // get handled in the next else.
1870 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1871 } else {
1872 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1873 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1874 goto Done;
1875 }
1876
1877 // --- Get the mantissa ---
1878 QCBORItem mantissaItem;
1879 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1880 if(nReturn != QCBOR_SUCCESS) {
1881 goto Done;
1882 }
1883 if(mantissaItem.uNestingLevel != nNestLevel) {
1884 // Mantissa missing or map/array encountered when expecting number
1885 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1886 goto Done;
1887 }
1888 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1889 // Data arriving as an unsigned int < INT64_MAX has been converted
1890 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1891 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1892 // will be too large for this to handle and thus an error that
1893 // will get handled in an else below.
1894 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001895 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1896 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897 // Got a good big num mantissa
1898 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1899 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001900 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1901 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1902 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001903 } else {
1904 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1905 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1906 goto Done;
1907 }
1908
1909 // --- Check that array only has the two numbers ---
1910 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001911 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001912 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1913 goto Done;
1914 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001915 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001916
1917Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001918 return nReturn;
1919}
1920#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1921
1922
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001923static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001924{
1925 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1926 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001927 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001928 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1929 } else {
1930 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001931
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001932 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001933
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001934 return QCBOR_SUCCESS;
1935}
1936
1937
Laurence Lundblade99615302020-11-29 11:19:47 -08001938/*
1939 * Table of CBOR tags whose content is either a text string or a byte
1940 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1941 * of uQCBORtype indicates the content should be a byte string rather
1942 * than a text string
1943 */
1944struct StringTagMapEntry {
1945 uint16_t uTagNumber;
1946 uint8_t uQCBORtype;
1947};
1948
1949#define IS_BYTE_STRING_BIT 0x80
1950#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1951
1952static const struct StringTagMapEntry StringTagMap[] = {
1953 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1954 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1955 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1956 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1957 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1958 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1959 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1960 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1961 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1962 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1963 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1964};
1965
1966
1967/*
1968 * Process the CBOR tags that whose content is a byte string or a text
1969 * string and for which the string is just passed on to the caller.
1970 *
1971 * This maps the CBOR tag to the QCBOR type and checks the content
1972 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001973 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001974 * possible.
1975 *
1976 * This returns QCBOR_SUCCESS if the tag was procssed,
1977 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1978 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1979 */
1980static inline
1981QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001982{
Laurence Lundblade99615302020-11-29 11:19:47 -08001983 /* This only works on tags that were not mapped; no need for other yet */
1984 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1985 return QCBOR_ERR_UNSUPPORTED;
1986 }
1987
1988 unsigned uIndex;
1989 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1990 if(StringTagMap[uIndex].uTagNumber == uTag) {
1991 break;
1992 }
1993 }
1994
1995 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1996 if(uQCBORType == QCBOR_TYPE_NONE) {
1997 /* repurpose this error to mean, not handled here */
1998 return QCBOR_ERR_UNSUPPORTED;
1999 }
2000
2001 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2002 if(uQCBORType & IS_BYTE_STRING_BIT) {
2003 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2004 }
2005
2006 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002007 return QCBOR_ERR_BAD_OPT_TAG;
2008 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002009
Laurence Lundblade99615302020-11-29 11:19:47 -08002010 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002011 return QCBOR_SUCCESS;
2012}
2013
2014
Laurence Lundblade59289e52019-12-30 13:44:37 -08002015/*
Laurence Lundblade99615302020-11-29 11:19:47 -08002016 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2017 * but the whole tag was not decoded. Here, the whole tags (tag number
2018 * and tag content) that are supported by QCBOR are decoded. This is a
2019 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002020 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002021static QCBORError
2022QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002023{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002024 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002026 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2027 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002028 goto Done;
2029 }
2030
Laurence Lundblade99615302020-11-29 11:19:47 -08002031 /* When there are no tag numbers for the item, this exits first
2032 * thing and effectively does nothing.
2033 *
2034 * This loops over all the tag numbers accumulated for this item
2035 * trying to decode and interpret them. This stops at the end of
2036 * the list or at the first tag number that can't be interpreted by
2037 * this code. This is effectively a recursive processing of the
2038 * tags number list that handles nested tags.
2039 */
2040 while(1) {
2041 /* Don't bother to unmap tags via QCBORITem.uTags since this
2042 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2043 */
2044 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002045
Laurence Lundblade99615302020-11-29 11:19:47 -08002046 if(uTagToProcess == CBOR_TAG_INVALID16) {
2047 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 break;
2049
Laurence Lundblade99615302020-11-29 11:19:47 -08002050 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002051 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052
Laurence Lundblade93d89472020-10-03 22:30:50 -07002053#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002054 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2055 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002056 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002057#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002058
Laurence Lundblade99615302020-11-29 11:19:47 -08002059 } else if(uTagToProcess == CBOR_TAG_MIME ||
2060 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002061 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002062
Laurence Lundblade99615302020-11-29 11:19:47 -08002063 } else {
2064 /* See if it is a pass-through byte/text string tag; process if so */
2065 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002066
Laurence Lundblade99615302020-11-29 11:19:47 -08002067 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2068 /* It wasn't a pass-through byte/text string tag so it is
2069 * an unknown tag. This is the exit from the loop on the
2070 * first unknown tag. It is a successful exit.
2071 */
2072 uReturn = QCBOR_SUCCESS;
2073 break;
2074 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002075 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002076
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002077 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002078 /* Error exit from the loop */
2079 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002080 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002081
2082 /* A tag was successfully processed, shift it out of the list of
2083 * tags returned. This is the loop increment.
2084 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002085 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002086 }
2087
2088Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002089 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002090}
2091
2092
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002093/*
2094 Public function, see header qcbor/qcbor_decode.h file
2095 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002096QCBORError
2097QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2098{
2099 QCBORError uErr;
2100 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2101 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2103 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2104 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002105 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002106}
2107
2108
2109/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002110 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002111 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002112QCBORError
2113QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2114{
2115 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2116 const UsefulInputBuf Save = pMe->InBuf;
2117
2118 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2119
2120 pMe->nesting = SaveNesting;
2121 pMe->InBuf = Save;
2122
2123 return uErr;
2124}
2125
2126
2127/*
2128 Public function, see header qcbor/qcbor_decode.h file
2129 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002130void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2131{
2132 if(pMe->uLastError != QCBOR_SUCCESS) {
2133 return;
2134 }
2135
2136 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2137}
2138
2139
2140/*
2141 Public function, see header qcbor/qcbor_decode.h file
2142 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002143QCBORError
2144QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2145 QCBORItem *pDecodedItem,
2146 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002147{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002148 QCBORError nReturn;
2149
2150 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2151 if(nReturn != QCBOR_SUCCESS) {
2152 return nReturn;
2153 }
2154
2155 if(pTags != NULL) {
2156 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002157 // Reverse the order because pTags is reverse of
2158 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002159 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2160 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002161 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002162 }
2163 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2164 return QCBOR_ERR_TOO_MANY_TAGS;
2165 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002166 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002167 pTags->uNumUsed++;
2168 }
2169 }
2170
2171 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002172}
2173
2174
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002175/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302176 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302177 next one down. If a layer has no work to do for a particular item
2178 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002179
Laurence Lundblade59289e52019-12-30 13:44:37 -08002180 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2181 tagged data items, turning them into the local C representation.
2182 For the most simple it is just associating a QCBOR_TYPE with the data. For
2183 the complex ones that an aggregate of data items, there is some further
2184 decoding and a little bit of recursion.
2185
2186 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302187 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302188 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002189 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002190
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302191 - GetNext_MapEntry -- This handles the combining of two
2192 items, the label and the data, that make up a map entry.
2193 It only does work on maps. It combines the label and data
2194 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002195
Laurence Lundblade59289e52019-12-30 13:44:37 -08002196 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2197 tags into bit flags associated with the data item. No actual decoding
2198 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002199
Laurence Lundblade59289e52019-12-30 13:44:37 -08002200 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302201 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302202 string allocater to create contiguous space for the item. It
2203 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002204
Laurence Lundblade59289e52019-12-30 13:44:37 -08002205 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2206 atomic data item has a "major type", an integer "argument" and optionally
2207 some content. For text and byte strings, the content is the bytes
2208 that make up the string. These are the smallest data items that are
2209 considered to be well-formed. The content may also be other data items in
2210 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002211
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002212 Roughly this takes 300 bytes of stack for vars. Need to
2213 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002214
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302215 */
2216
2217
2218/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002219 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002220 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002221bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002222 const QCBORItem *pItem,
2223 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002224{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002225 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2226 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002227 break;
2228 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002229 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002230 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002231 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002234 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002235}
2236
2237
2238/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002239 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002240 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002241QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002242{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002243 QCBORError uReturn = me->uLastError;
2244
2245 if(uReturn != QCBOR_SUCCESS) {
2246 goto Done;
2247 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002249 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002250 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002251 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002252 goto Done;
2253 }
2254
2255 // Error out if not all the bytes are consumed
2256 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002257 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002259
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002260Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002261#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302262 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002263 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002264 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002265#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002266
Laurence Lundblade085d7952020-07-24 10:26:30 -07002267 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002268}
2269
2270
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002271/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002272 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002273*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002274// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002275uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2276 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002277 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002278{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002279 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2280 return CBOR_TAG_INVALID64;
2281 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002282 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2283 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002284 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002285 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002286 }
2287}
2288
Laurence Lundblade9b334962020-08-27 10:55:53 -07002289/*
2290 Public function, see header qcbor/qcbor_decode.h file
2291*/
2292uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2293 uint32_t uIndex)
2294{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002295 if(pMe->uLastError != QCBOR_SUCCESS) {
2296 return CBOR_TAG_INVALID64;
2297 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002298 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2299 return CBOR_TAG_INVALID64;
2300 } else {
2301 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2302 }
2303}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002304
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002305/*
2306
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002307Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002308
Laurence Lundbladeee851742020-01-08 08:37:05 -08002309 - Hit end of input before it was expected while decoding type and
2310 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002311
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002312 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002313
Laurence Lundbladeee851742020-01-08 08:37:05 -08002314 - Hit end of input while decoding a text or byte string
2315 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002316
Laurence Lundbladeee851742020-01-08 08:37:05 -08002317 - Encountered conflicting tags -- e.g., an item is tagged both a date
2318 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002319
Laurence Lundbladeee851742020-01-08 08:37:05 -08002320 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002321 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002322
Laurence Lundbladeee851742020-01-08 08:37:05 -08002323 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002324 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002325
Laurence Lundbladeee851742020-01-08 08:37:05 -08002326 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2327 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002328
Laurence Lundbladeee851742020-01-08 08:37:05 -08002329 - The type of a map label is not a string or int
2330 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002331
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002332 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002333
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002334 */
2335
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002336
2337
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002338#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002339
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002340/* ===========================================================================
2341 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002342
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002343 This implements a simple sting allocator for indefinite length
2344 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2345 implements the function type QCBORStringAllocate and allows easy
2346 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002347
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002348 This particular allocator is built-in for convenience. The caller
2349 can implement their own. All of this following code will get
2350 dead-stripped if QCBORDecode_SetMemPool() is not called.
2351
2352 This is a very primitive memory allocator. It does not track
2353 individual allocations, only a high-water mark. A free or
2354 reallocation must be of the last chunk allocated.
2355
2356 The size of the pool and offset to free memory are packed into the
2357 first 8 bytes of the memory pool so we don't have to keep them in
2358 the decode context. Since the address of the pool may not be
2359 aligned, they have to be packed and unpacked as if they were
2360 serialized data of the wire or such.
2361
2362 The sizes packed in are uint32_t to be the same on all CPU types
2363 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002364 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002365
2366
Laurence Lundbladeee851742020-01-08 08:37:05 -08002367static inline int
2368MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002369{
2370 // Use of UsefulInputBuf is overkill, but it is convenient.
2371 UsefulInputBuf UIB;
2372
Laurence Lundbladeee851742020-01-08 08:37:05 -08002373 // Just assume the size here. It was checked during SetUp so
2374 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002375 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002376 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2377 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2378 return UsefulInputBuf_GetError(&UIB);
2379}
2380
2381
Laurence Lundbladeee851742020-01-08 08:37:05 -08002382static inline int
2383MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002384{
2385 // Use of UsefulOutBuf is overkill, but convenient. The
2386 // length check performed here is useful.
2387 UsefulOutBuf UOB;
2388
2389 UsefulOutBuf_Init(&UOB, Pool);
2390 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2391 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2392 return UsefulOutBuf_GetError(&UOB);
2393}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002394
2395
2396/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002397 Internal function for an allocation, reallocation free and destuct.
2398
2399 Having only one function rather than one each per mode saves space in
2400 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002401
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002402 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2403 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002404static UsefulBuf
2405MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002406{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002407 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002408
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002409 uint32_t uPoolSize;
2410 uint32_t uFreeOffset;
2411
2412 if(uNewSize > UINT32_MAX) {
2413 // This allocator is only good up to 4GB. This check should
2414 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2415 goto Done;
2416 }
2417 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2418
2419 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2420 goto Done;
2421 }
2422
2423 if(uNewSize) {
2424 if(pMem) {
2425 // REALLOCATION MODE
2426 // Calculate pointer to the end of the memory pool. It is
2427 // assumed that pPool + uPoolSize won't wrap around by
2428 // assuming the caller won't pass a pool buffer in that is
2429 // not in legitimate memory space.
2430 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2431
2432 // Check that the pointer for reallocation is in the range of the
2433 // pool. This also makes sure that pointer math further down
2434 // doesn't wrap under or over.
2435 if(pMem >= pPool && pMem < pPoolEnd) {
2436 // Offset to start of chunk for reallocation. This won't
2437 // wrap under because of check that pMem >= pPool. Cast
2438 // is safe because the pool is always less than UINT32_MAX
2439 // because of check in QCBORDecode_SetMemPool().
2440 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2441
2442 // Check to see if the allocation will fit. uPoolSize -
2443 // uMemOffset will not wrap under because of check that
2444 // pMem is in the range of the uPoolSize by check above.
2445 if(uNewSize <= uPoolSize - uMemOffset) {
2446 ReturnValue.ptr = pMem;
2447 ReturnValue.len = uNewSize;
2448
2449 // Addition won't wrap around over because uNewSize was
2450 // checked to be sure it is less than the pool size.
2451 uFreeOffset = uMemOffset + uNewSize32;
2452 }
2453 }
2454 } else {
2455 // ALLOCATION MODE
2456 // uPoolSize - uFreeOffset will not underflow because this
2457 // pool implementation makes sure uFreeOffset is always
2458 // smaller than uPoolSize through this check here and
2459 // reallocation case.
2460 if(uNewSize <= uPoolSize - uFreeOffset) {
2461 ReturnValue.len = uNewSize;
2462 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002463 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002464 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002465 }
2466 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002467 if(pMem) {
2468 // FREE MODE
2469 // Cast is safe because of limit on pool size in
2470 // QCBORDecode_SetMemPool()
2471 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2472 } else {
2473 // DESTRUCT MODE
2474 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002475 }
2476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002477
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002478 UsefulBuf Pool = {pPool, uPoolSize};
2479 MemPool_Pack(Pool, uFreeOffset);
2480
2481Done:
2482 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002483}
2484
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002485
Laurence Lundbladef6531662018-12-04 10:42:22 +09002486/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002487 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002488 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002489QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2490 UsefulBuf Pool,
2491 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002492{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002493 // The pool size and free mem offset are packed into the beginning
2494 // of the pool memory. This compile time check make sure the
2495 // constant in the header is correct. This check should optimize
2496 // down to nothing.
2497 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002498 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002499 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002500
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002501 // The pool size and free offset packed in to the beginning of pool
2502 // memory are only 32-bits. This check will optimize out on 32-bit
2503 // machines.
2504 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002505 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002506 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002507
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002508 // This checks that the pool buffer given is big enough.
2509 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002510 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002511 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002512
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002513 pMe->StringAllocator.pfAllocator = MemPool_Function;
2514 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2515 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002516
Laurence Lundblade30816f22018-11-10 13:40:22 +07002517 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002518}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002519#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002520
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002521
2522
Laurence Lundblade9b334962020-08-27 10:55:53 -07002523static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2524{
2525 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2526}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002527
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002528
2529/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002530 Consume an entire map or array (and do next to
2531 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002532 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002533static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002534ConsumeItem(QCBORDecodeContext *pMe,
2535 const QCBORItem *pItemToConsume,
2536 uint_fast8_t *puNextNestLevel)
2537{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002538 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002540
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002541 // If it is a map or array, this will tell if it is empty.
2542 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2543
2544 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2545 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002546
Laurence Lundblade1341c592020-04-11 14:19:05 -07002547 /* This works for definite and indefinite length
2548 * maps and arrays by using the nesting level
2549 */
2550 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002551 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002552 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002553 goto Done;
2554 }
2555 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002556
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002557 *puNextNestLevel = Item.uNextNestLevel;
2558
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002559 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560
Laurence Lundblade1341c592020-04-11 14:19:05 -07002561 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002562 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002563 /* Just pass the nesting level through */
2564 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2565
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002566 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002567 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002568
2569Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002570 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002571}
2572
2573
Laurence Lundblade1341c592020-04-11 14:19:05 -07002574/* Return true if the labels in Item1 and Item2 are the same.
2575 Works only for integer and string labels. Returns false
2576 for any other type. */
2577static inline bool
2578MatchLabel(QCBORItem Item1, QCBORItem Item2)
2579{
2580 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2581 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2582 return true;
2583 }
2584 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002585 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002586 return true;
2587 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002588 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002589 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2590 return true;
2591 }
2592 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2593 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2594 return true;
2595 }
2596 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002597
Laurence Lundblade1341c592020-04-11 14:19:05 -07002598 /* Other label types are never matched */
2599 return false;
2600}
2601
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002602
2603/*
2604 Returns true if Item1 and Item2 are the same type
2605 or if either are of QCBOR_TYPE_ANY.
2606 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002607static inline bool
2608MatchType(QCBORItem Item1, QCBORItem Item2)
2609{
2610 if(Item1.uDataType == Item2.uDataType) {
2611 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002612 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002613 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002614 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002615 return true;
2616 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002617 return false;
2618}
2619
2620
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002621/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002622 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002623
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002624 @param[in] pMe The decode context to search.
2625 @param[in,out] pItemArray The items to search for and the items found.
2626 @param[out] puOffset Byte offset of last item matched.
2627 @param[in] pCBContext Context for the not-found item call back.
2628 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002629
2630 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2631
Laurence Lundblade93d89472020-10-03 22:30:50 -07002632 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2633 were found for one of the labels being
2634 search for. This duplicate detection is
2635 only performed for items in pItemArray,
2636 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002637
Laurence Lundblade93d89472020-10-03 22:30:50 -07002638 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2639 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002640
2641 @retval Also errors returned by QCBORDecode_GetNext().
2642
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002643 On input pItemArray contains a list of labels and data types
2644 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002645
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002646 On output the fully retrieved items are filled in with
2647 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002648
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002649 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002650
2651 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002652 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002653static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002654MapSearch(QCBORDecodeContext *pMe,
2655 QCBORItem *pItemArray,
2656 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002657 void *pCBContext,
2658 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002659{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002660 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002661 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002662
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002663 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002664 uReturn = pMe->uLastError;
2665 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002666 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002667
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002668 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002669 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2670 /* QCBOR_TYPE_NONE as first item indicates just looking
2671 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002672 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2673 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002674 }
2675
Laurence Lundblade085d7952020-07-24 10:26:30 -07002676 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2677 // It is an empty bounded array or map
2678 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2679 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002680 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002681 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002682 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002683 // Nothing is ever found in an empty array or map. All items
2684 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002685 uReturn = QCBOR_SUCCESS;
2686 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002687 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002688 }
2689
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002690 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002691 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2692
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002693 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002694 UsefulInputBuf_Seek(&(pMe->InBuf),
2695 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002696
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002697 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002698 Loop over all the items in the map or array. Each item
2699 could be a map or array, but label matching is only at
2700 the main level. This handles definite and indefinite
2701 length maps and arrays. The only reason this is ever
2702 called on arrays is to find their end position.
2703
2704 This will always run over all items in order to do
2705 duplicate detection.
2706
2707 This will exit with failure if it encounters an
2708 unrecoverable error, but continue on for recoverable
2709 errors.
2710
2711 If a recoverable error occurs on a matched item, then
2712 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002713 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002714 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002715 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002716 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002717 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002718 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002719
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002720 /* Get the item */
2721 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002722 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2723 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002724 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002725 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002726 goto Done;
2727 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002728 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002729 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002730 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002731 goto Done;
2732 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002733
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002734 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002735 bool bMatched = false;
2736 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2737 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002738 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002739 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2740 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002742 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002743 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002744 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002745 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002746 goto Done;
2747 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002748
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002749 if(uResult != QCBOR_SUCCESS) {
2750 uReturn = uResult;
2751 goto Done;
2752 }
2753
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002755 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002756 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002757 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002758 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002759 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002760 bMatched = true;
2761 }
2762 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002763
2764
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002765 if(!bMatched && pfCallback != NULL) {
2766 /*
2767 Call the callback on unmatched labels.
2768 (It is tempting to do duplicate detection here, but that would
2769 require dynamic memory allocation because the number of labels
2770 that might be encountered is unbounded.)
2771 */
2772 uReturn = (*pfCallback)(pCBContext, &Item);
2773 if(uReturn != QCBOR_SUCCESS) {
2774 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002775 }
2776 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002777
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002778 /*
2779 Consume the item whether matched or not. This
2780 does the work of traversing maps and array and
2781 everything in them. In this loop only the
2782 items at the current nesting level are examined
2783 to match the labels.
2784 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002785 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002786 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787 goto Done;
2788 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002789
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002790 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002791
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002792 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002793
2794 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002795
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002796 // Check here makes sure that this won't accidentally be
2797 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002798 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002799 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2800 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002801 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2802 goto Done;
2803 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002804 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2805 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002806
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002807 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002808 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2809
2810 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002811 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002812 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002813 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002814 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2815 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002816 }
2817 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002818
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002819 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002820}
2821
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002822
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002823/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002824 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002825*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002826void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2827 int64_t nLabel,
2828 uint8_t uQcborType,
2829 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002830{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002831 if(pMe->uLastError != QCBOR_SUCCESS) {
2832 return;
2833 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002834
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002835 QCBORItem OneItemSeach[2];
2836 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2837 OneItemSeach[0].label.int64 = nLabel;
2838 OneItemSeach[0].uDataType = uQcborType;
2839 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002840
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002841 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002842
2843 *pItem = OneItemSeach[0];
2844
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002845 if(uReturn != QCBOR_SUCCESS) {
2846 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002847 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002848 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002849 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002850 }
2851
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002852 Done:
2853 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002854}
2855
2856
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002857/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002858 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002859*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002860void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2861 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002862 uint8_t uQcborType,
2863 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002864{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002865 if(pMe->uLastError != QCBOR_SUCCESS) {
2866 return;
2867 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002868
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002869 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002870 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2871 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2872 OneItemSeach[0].uDataType = uQcborType;
2873 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002874
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002875 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2876 if(uReturn != QCBOR_SUCCESS) {
2877 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002878 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002879 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002880 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002881 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002882 }
2883
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002884 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002885
2886Done:
2887 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002888}
2889
2890
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002891
Laurence Lundblade93d89472020-10-03 22:30:50 -07002892static QCBORError
2893CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002894{
2895 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2896 if(uDataType == puTypeList[i]) {
2897 return QCBOR_SUCCESS;
2898 }
2899 }
2900 return QCBOR_ERR_UNEXPECTED_TYPE;
2901}
2902
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002903
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002904/**
2905 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002906 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002907
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002908 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2909 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002910
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002911 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2912 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002913 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002914static QCBORError
2915CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002916{
2917 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2918 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2919 /* There are tags that QCBOR couldn't process on this item and
2920 the caller has told us there should not be. */
2921 return QCBOR_ERR_UNEXPECTED_TYPE;
2922 }
2923
2924 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2925 const int nItemType = pItem->uDataType;
2926
2927 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2928 // Must match the tag and only the tag
2929 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2930 }
2931
2932 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2933 if(uReturn == QCBOR_SUCCESS) {
2934 return QCBOR_SUCCESS;
2935 }
2936
2937 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2938 /* Must match the content type and only the content type.
2939 There was no match just above so it is a fail. */
2940 return QCBOR_ERR_UNEXPECTED_TYPE;
2941 }
2942
2943 /* If here it can match either the tag or the content
2944 and it hasn't matched the content, so the end
2945 result is whether it matches the tag. This is
2946 also the case that the CBOR standard discourages. */
2947
2948 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2949}
2950
Laurence Lundblade9b334962020-08-27 10:55:53 -07002951
Laurence Lundblade9b334962020-08-27 10:55:53 -07002952
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002953// This could be semi-private if need be
2954static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002955void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2956 int64_t nLabel,
2957 TagSpecification TagSpec,
2958 QCBORItem *pItem)
2959{
2960 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2961 if(pMe->uLastError != QCBOR_SUCCESS) {
2962 return;
2963 }
2964
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002965 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002966}
2967
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002968
2969// This could be semi-private if need be
2970static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002971void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2972 const char *szLabel,
2973 TagSpecification TagSpec,
2974 QCBORItem *pItem)
2975{
2976 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2977 if(pMe->uLastError != QCBOR_SUCCESS) {
2978 return;
2979 }
2980
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002981 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002982}
2983
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002984// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002985void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2986 int64_t nLabel,
2987 TagSpecification TagSpec,
2988 UsefulBufC *pString)
2989{
2990 QCBORItem Item;
2991 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2992 if(pMe->uLastError == QCBOR_SUCCESS) {
2993 *pString = Item.val.string;
2994 }
2995}
2996
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002997// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002998void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2999 const char * szLabel,
3000 TagSpecification TagSpec,
3001 UsefulBufC *pString)
3002{
3003 QCBORItem Item;
3004 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3005 if(pMe->uLastError == QCBOR_SUCCESS) {
3006 *pString = Item.val.string;
3007 }
3008}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003009
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003010/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003011 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003012*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003013void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003014{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003015 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3016 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003017}
3018
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003019/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003020 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003021*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003022void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3023 QCBORItem *pItemList,
3024 void *pCallbackCtx,
3025 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003026{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003027 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3028 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003029}
3030
3031
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003032/**
3033 * @brief Search for a map/array by label and enter it
3034 *
3035 * @param[in] pMe The decode context.
3036 * @param[in] pSearch The map/array to search for.
3037 *
3038 * @c pSearch is expected to contain one item of type map or array
3039 * with the label specified. The current bounded map will be searched for
3040 * this and if found will be entered.
3041 *
3042 * If the label is not found, or the item found is not a map or array,
3043 * the error state is set.
3044 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003045static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003047 // The first item in pSearch is the one that is to be
3048 // entered. It should be the only one filled in. Any other
3049 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003050 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003051 return;
3052 }
3053
3054 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003055 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003056 if(pMe->uLastError != QCBOR_SUCCESS) {
3057 return;
3058 }
3059
Laurence Lundblade9b334962020-08-27 10:55:53 -07003060 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003061 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003062 return;
3063 }
3064
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003065 /*
3066 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3067 * next item for the pre-order traversal cursor to be the map/array
3068 * found by MapSearch(). The next few lines of code force the
3069 * cursor to that.
3070 *
3071 * There is no need to retain the old cursor because
3072 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3073 * beginning of the map/array being entered.
3074 *
3075 * The cursor is forced by: 1) setting the input buffer position to
3076 * the item offset found by MapSearch(), 2) setting the map/array
3077 * counter to the total in the map/array, 3) setting the nesting
3078 * level. Setting the map/array counter to the total is not
3079 * strictly correct, but this is OK because this cursor only needs
3080 * to be used to get one item and MapSearch() has already found it
3081 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003082 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003083 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003084
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003085 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3086
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003087 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003088
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003089 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003090}
3091
3092
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003093/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003094 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003095*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003096void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003098 QCBORItem OneItemSeach[2];
3099 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3100 OneItemSeach[0].label.int64 = nLabel;
3101 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3102 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003103
Laurence Lundblade9b334962020-08-27 10:55:53 -07003104 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003105 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003106}
3107
3108
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003109/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003110 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003111*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003112void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003113{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003114 QCBORItem OneItemSeach[2];
3115 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3116 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3117 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3118 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003119
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003120 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003121}
3122
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003123/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003124 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003125*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003126void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003127{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003128 QCBORItem OneItemSeach[2];
3129 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3130 OneItemSeach[0].label.int64 = nLabel;
3131 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3132 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003133
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003134 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003135}
3136
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003137/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003138 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003139*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003140void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3141{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003142 QCBORItem OneItemSeach[2];
3143 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3144 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3145 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3146 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003147
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003148 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003149}
3150
3151
Laurence Lundblade02625d42020-06-25 14:41:41 -07003152// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003153void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003154{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003155 QCBORError uErr;
3156
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003157 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003158 if(pMe->uLastError != QCBOR_SUCCESS) {
3159 // Already in error state; do nothing.
3160 return;
3161 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003162
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003163 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003164 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003165 uErr = QCBORDecode_GetNext(pMe, &Item);
3166 if(uErr != QCBOR_SUCCESS) {
3167 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003168 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003169 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003170 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3171 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003172 }
3173
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003174 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003175
3176
Laurence Lundbladef0499502020-08-01 11:55:57 -07003177 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003178 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003179 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3180 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003181 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003182 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3183 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003184 // Special case to increment nesting level for zero-length maps
3185 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003186 DecodeNesting_Descend(&(pMe->nesting), uType);
3187 }
3188
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003189 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003190
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003191 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3192 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003193
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003194 if(pItem != NULL) {
3195 *pItem = Item;
3196 }
3197
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003198Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003199 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003200}
3201
Laurence Lundblade02625d42020-06-25 14:41:41 -07003202
3203/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003204 This is the common work for exiting a level that is a bounded map,
3205 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003206
3207 One chunk of work is to set up the pre-order traversal so it is at
3208 the item just after the bounded map, array or bstr that is being
3209 exited. This is somewhat complex.
3210
3211 The other work is to level-up the bounded mode to next higest bounded
3212 mode or the top level if there isn't one.
3213 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003214static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003215ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003216{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003217 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003218
Laurence Lundblade02625d42020-06-25 14:41:41 -07003219 /*
3220 First the pre-order-traversal byte offset is positioned to the
3221 item just after the bounded mode item that was just consumed.
3222 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003223 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3224
Laurence Lundblade02625d42020-06-25 14:41:41 -07003225 /*
3226 Next, set the current nesting level to one above the bounded level
3227 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003228
Laurence Lundblade02625d42020-06-25 14:41:41 -07003229 DecodeNesting_CheckBoundedType() is always called before this and
3230 makes sure pCurrentBounded is valid.
3231 */
3232 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3233
3234 /*
3235 This does the complex work of leveling up the pre-order traversal
3236 when the end of a map or array or another bounded level is
3237 reached. It may do nothing, or ascend all the way to the top
3238 level.
3239 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003240 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003241 if(uErr != QCBOR_SUCCESS) {
3242 goto Done;
3243 }
3244
Laurence Lundblade02625d42020-06-25 14:41:41 -07003245 /*
3246 This makes the next highest bounded level the current bounded
3247 level. If there is no next highest level, then no bounded mode is
3248 in effect.
3249 */
3250 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003251
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003252 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003253
3254Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003255 return uErr;
3256}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003257
Laurence Lundblade02625d42020-06-25 14:41:41 -07003258
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003259// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003260void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003261{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003262 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003263 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003264 return;
3265 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003266
Laurence Lundblade02625d42020-06-25 14:41:41 -07003267 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003268
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003269 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003270 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003271 goto Done;
3272 }
3273
Laurence Lundblade02625d42020-06-25 14:41:41 -07003274 /*
3275 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003276 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003277 from previous map search, then do a dummy search.
3278 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003279 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003280 QCBORItem Dummy;
3281 Dummy.uLabelType = QCBOR_TYPE_NONE;
3282 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3283 if(uErr != QCBOR_SUCCESS) {
3284 goto Done;
3285 }
3286 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003287
Laurence Lundblade02625d42020-06-25 14:41:41 -07003288 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003289
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003290Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003291 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003292}
3293
3294
Laurence Lundblade1341c592020-04-11 14:19:05 -07003295
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003296static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003297 const QCBORItem *pItem,
3298 uint8_t uTagRequirement,
3299 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003300{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003301 if(pBstr) {
3302 *pBstr = NULLUsefulBufC;
3303 }
3304
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003305 if(pMe->uLastError != QCBOR_SUCCESS) {
3306 // Already in error state; do nothing.
3307 return pMe->uLastError;
3308 }
3309
3310 QCBORError uError = QCBOR_SUCCESS;
3311
3312 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3313 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3314 goto Done;;
3315 }
3316
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003317 const TagSpecification TagSpec =
3318 {
3319 uTagRequirement,
3320 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3321 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3322 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003323
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003324 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003325 if(uError != QCBOR_SUCCESS) {
3326 goto Done;
3327 }
3328
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003329 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003330 // Reverse the decrement done by GetNext() for the bstr so the
3331 // increment in NestLevelAscender() called by ExitBoundedLevel()
3332 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003333 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003334 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003335
3336 if(pBstr) {
3337 *pBstr = pItem->val.string;
3338 }
3339
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003340 // This saves the current length of the UsefulInputBuf and then
3341 // narrows the UsefulInputBuf to start and length of the wrapped
3342 // CBOR that is being entered.
3343 //
3344 // This makes sure the length is less than
3345 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3346 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3347 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3348 // the casts safe. uEndOfBstr will always be less than
3349 // uPreviousLength because of the way UsefulInputBuf works so there
3350 // is no need to check it. There is also a range check in the
3351 // seek.
3352 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003353 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003354 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003355 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003356 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003357 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003358 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003359 goto Done;
3360 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003361 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003362 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003363 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003364
Laurence Lundblade02625d42020-06-25 14:41:41 -07003365 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003366 (uint32_t)uPreviousLength,
3367 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003368Done:
3369 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003370}
3371
3372
Laurence Lundblade02625d42020-06-25 14:41:41 -07003373/*
3374 Public function, see header qcbor/qcbor_decode.h file
3375 */
3376void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003377 uint8_t uTagRequirement,
3378 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003379{
3380 if(pMe->uLastError != QCBOR_SUCCESS) {
3381 // Already in error state; do nothing.
3382 return;
3383 }
3384
3385 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003386 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003387 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3388 if(pMe->uLastError != QCBOR_SUCCESS) {
3389 return;
3390 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003391
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003392 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003393 &Item,
3394 uTagRequirement,
3395 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003396}
3397
3398
Laurence Lundblade02625d42020-06-25 14:41:41 -07003399/*
3400 Public function, see header qcbor/qcbor_decode.h file
3401 */
3402void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003403 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003404 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003405 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003406{
3407 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003408 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003409
Laurence Lundblade93d89472020-10-03 22:30:50 -07003410 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3411 &Item,
3412 uTagRequirement,
3413 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003414}
3415
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003416
Laurence Lundblade02625d42020-06-25 14:41:41 -07003417/*
3418 Public function, see header qcbor/qcbor_decode.h file
3419 */
3420void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003421 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003422 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003423 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003424{
3425 QCBORItem Item;
3426 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3427
Laurence Lundblade93d89472020-10-03 22:30:50 -07003428 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3429 &Item,
3430 uTagRequirement,
3431 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003432}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003433
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003434
Laurence Lundblade02625d42020-06-25 14:41:41 -07003435/*
3436 Public function, see header qcbor/qcbor_decode.h file
3437 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003438void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003439{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003440 if(pMe->uLastError != QCBOR_SUCCESS) {
3441 // Already in error state; do nothing.
3442 return;
3443 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003444
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003445 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003446 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003447 return;
3448 }
3449
3450 /*
3451 Reset the length of the UsefulInputBuf to what it was before
3452 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003453 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003454 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003455 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003456
3457
Laurence Lundblade02625d42020-06-25 14:41:41 -07003458 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003459 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003460}
3461
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003462
Laurence Lundbladee6430642020-03-14 21:15:44 -07003463
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003464
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003465
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003466
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003467
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003468
Laurence Lundblade93d89472020-10-03 22:30:50 -07003469static QCBORError
3470InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003471{
3472 switch(pItem->uDataType) {
3473 case QCBOR_TYPE_TRUE:
3474 *pBool = true;
3475 return QCBOR_SUCCESS;
3476 break;
3477
3478 case QCBOR_TYPE_FALSE:
3479 *pBool = false;
3480 return QCBOR_SUCCESS;
3481 break;
3482
3483 default:
3484 return QCBOR_ERR_UNEXPECTED_TYPE;
3485 break;
3486 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003487 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003488}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003489
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003490
Laurence Lundblade9b334962020-08-27 10:55:53 -07003491
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003492/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003493 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003494*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003495void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003496{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003497 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003498 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003499 return;
3500 }
3501
Laurence Lundbladec4537442020-04-14 18:53:22 -07003502 QCBORError nError;
3503 QCBORItem Item;
3504
3505 nError = QCBORDecode_GetNext(pMe, &Item);
3506 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003507 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003508 return;
3509 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003510 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003511}
3512
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003513
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003514/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003515 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003516*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003517void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003518{
3519 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003520 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003521
Laurence Lundblade9b334962020-08-27 10:55:53 -07003522 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003523}
3524
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003525
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003526/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003527 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003528*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003529void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3530{
3531 QCBORItem Item;
3532 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3533
Laurence Lundblade9b334962020-08-27 10:55:53 -07003534 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003535}
3536
3537
3538
Laurence Lundbladec7114722020-08-13 05:11:40 -07003539
3540static void ProcessEpochDate(QCBORDecodeContext *pMe,
3541 QCBORItem *pItem,
3542 uint8_t uTagRequirement,
3543 int64_t *pnTime)
3544{
3545 if(pMe->uLastError != QCBOR_SUCCESS) {
3546 // Already in error state, do nothing
3547 return;
3548 }
3549
3550 QCBORError uErr;
3551
3552 const TagSpecification TagSpec =
3553 {
3554 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003555 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3556 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003557 };
3558
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003559 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003560 if(uErr != QCBOR_SUCCESS) {
3561 goto Done;
3562 }
3563
3564 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3565 uErr = DecodeDateEpoch(pItem);
3566 if(uErr != QCBOR_SUCCESS) {
3567 goto Done;
3568 }
3569 }
3570
Laurence Lundblade9b334962020-08-27 10:55:53 -07003571 // Save the tags in the last item's tags in the decode context
3572 // for QCBORDecode_GetNthTagOfLast()
3573 CopyTags(pMe, pItem);
3574
Laurence Lundbladec7114722020-08-13 05:11:40 -07003575 *pnTime = pItem->val.epochDate.nSeconds;
3576
3577Done:
3578 pMe->uLastError = (uint8_t)uErr;
3579}
3580
3581
3582void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003583 uint8_t uTagRequirement,
3584 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003585{
3586 if(pMe->uLastError != QCBOR_SUCCESS) {
3587 // Already in error state, do nothing
3588 return;
3589 }
3590
3591 QCBORItem Item;
3592 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3593
3594 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3595}
3596
3597
3598void
3599QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3600 int64_t nLabel,
3601 uint8_t uTagRequirement,
3602 int64_t *pnTime)
3603{
3604 QCBORItem Item;
3605 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3606 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3607}
3608
3609
3610void
3611QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3612 const char *szLabel,
3613 uint8_t uTagRequirement,
3614 int64_t *pnTime)
3615{
3616 QCBORItem Item;
3617 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3618 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3619}
3620
3621
3622
3623
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003624void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3625 TagSpecification TagSpec,
3626 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003628 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003629 // Already in error state, do nothing
3630 return;
3631 }
3632
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003633 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003634 QCBORItem Item;
3635
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003636 uError = QCBORDecode_GetNext(pMe, &Item);
3637 if(uError != QCBOR_SUCCESS) {
3638 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003639 return;
3640 }
3641
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003642 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003643
3644 if(pMe->uLastError == QCBOR_SUCCESS) {
3645 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003646 } else {
3647 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003648 }
3649}
3650
Laurence Lundbladec4537442020-04-14 18:53:22 -07003651
3652
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003654static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003655 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003656 UsefulBufC *pValue,
3657 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003658{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003659 const TagSpecification TagSpec =
3660 {
3661 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003662 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3663 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003664 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003665
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003666 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003667 if(uErr != QCBOR_SUCCESS) {
3668 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003669 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003670
3671 *pValue = pItem->val.string;
3672
3673 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3674 *pbIsNegative = false;
3675 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3676 *pbIsNegative = true;
3677 }
3678
3679 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003680}
3681
3682
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003683/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003684 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003685 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003686void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3687 uint8_t uTagRequirement,
3688 UsefulBufC *pValue,
3689 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003690{
3691 if(pMe->uLastError != QCBOR_SUCCESS) {
3692 // Already in error state, do nothing
3693 return;
3694 }
3695
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003696 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003697 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3698 if(uError != QCBOR_SUCCESS) {
3699 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003700 return;
3701 }
3702
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003703 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003704}
3705
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003706
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003707/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003708 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003709*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003710void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3711 int64_t nLabel,
3712 uint8_t uTagRequirement,
3713 UsefulBufC *pValue,
3714 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003715{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003716 QCBORItem Item;
3717 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003718 if(pMe->uLastError != QCBOR_SUCCESS) {
3719 return;
3720 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003721
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003722 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003723}
3724
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003725
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003726/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003727 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003728*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003729void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3730 const char *szLabel,
3731 uint8_t uTagRequirement,
3732 UsefulBufC *pValue,
3733 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003734{
3735 QCBORItem Item;
3736 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003737 if(pMe->uLastError != QCBOR_SUCCESS) {
3738 return;
3739 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003740
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003741 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003742}
3743
3744
3745
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003746
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003747// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003748QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3749 const QCBORItem *pItem,
3750 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003751 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003752{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003753 const TagSpecification TagSpecText =
3754 {
3755 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003756 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3757 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003758 };
3759 const TagSpecification TagSpecBinary =
3760 {
3761 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003762 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3763 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003764 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003765
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003766 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003767
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003768 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003769 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003770 if(pbIsTag257 != NULL) {
3771 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003772 }
3773 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003774 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003775 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003776 if(pbIsTag257 != NULL) {
3777 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003778 }
3779 uReturn = QCBOR_SUCCESS;
3780
3781 } else {
3782 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3783 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003784
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003785 return uReturn;
3786}
3787
Laurence Lundblade93d89472020-10-03 22:30:50 -07003788// Improvement: add methods for wrapped CBOR, a simple alternate
3789// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003790
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003791
3792
3793
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003794#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003795
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003797
3798
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003799// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003800static QCBORError
3801Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003802{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003803 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003805 if(uResult != 0) {
3806 /* This loop will run a maximum of 19 times because
3807 * UINT64_MAX < 10 ^^ 19. More than that will cause
3808 * exit with the overflow error
3809 */
3810 for(; nExponent > 0; nExponent--) {
3811 if(uResult > UINT64_MAX / 10) {
3812 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3813 }
3814 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003815 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003816
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003817 for(; nExponent < 0; nExponent++) {
3818 uResult = uResult / 10;
3819 if(uResult == 0) {
3820 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3821 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003822 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003823 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003824 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003825
3826 *puResult = uResult;
3827
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003829}
3830
3831
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003832// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003833static QCBORError
3834Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003835{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003836 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003837
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003838 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003839
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003841 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003842 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003843 */
3844 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003845 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003846 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003848 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003849 nExponent--;
3850 }
3851
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003852 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003853 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003854 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3855 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003856 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003857 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003858 }
3859
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003860 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003861
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003862 return QCBOR_SUCCESS;
3863}
3864
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003865
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003866/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003867 Compute value with signed mantissa and signed result. Works with
3868 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003869 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003870static inline QCBORError ExponentiateNN(int64_t nMantissa,
3871 int64_t nExponent,
3872 int64_t *pnResult,
3873 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003874{
3875 uint64_t uResult;
3876
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003877 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003878 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003879 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3880
3881 // Do the exponentiation of the positive mantissa
3882 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3883 if(uReturn) {
3884 return uReturn;
3885 }
3886
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003887
Laurence Lundblade983500d2020-05-14 11:49:34 -07003888 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3889 of INT64_MIN. This assumes two's compliment representation where
3890 INT64_MIN is one increment farther from 0 than INT64_MAX.
3891 Trying to write -INT64_MIN doesn't work to get this because the
3892 compiler tries to work with an int64_t which can't represent
3893 -INT64_MIN.
3894 */
3895 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3896
3897 // Error out if too large
3898 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003899 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3900 }
3901
3902 // Casts are safe because of checks above
3903 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3904
3905 return QCBOR_SUCCESS;
3906}
3907
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003908
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003909/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003910 Compute value with signed mantissa and unsigned result. Works with
3911 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003912 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003913static inline QCBORError ExponentitateNU(int64_t nMantissa,
3914 int64_t nExponent,
3915 uint64_t *puResult,
3916 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003917{
3918 if(nMantissa < 0) {
3919 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3920 }
3921
3922 // Cast to unsigned is OK because of check for negative
3923 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3924 // Exponentiation is straight forward
3925 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3926}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003927
3928
3929/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003930 Compute value with signed mantissa and unsigned result. Works with
3931 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003932 */
3933static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3934 int64_t nExponent,
3935 uint64_t *puResult,
3936 fExponentiator pfExp)
3937{
3938 return (*pfExp)(uMantissa, nExponent, puResult);
3939}
3940
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003941#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3942
3943
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003944
3945
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003946
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003947static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003948{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003949 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003950
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003951 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003952 const uint8_t *pByte = BigNum.ptr;
3953 size_t uLen = BigNum.len;
3954 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003955 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003956 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003958 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003959 }
3960
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003961 *pResult = uResult;
3962 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003963}
3964
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003965
Laurence Lundblade887add82020-05-17 05:50:34 -07003966static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003967{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003968 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003969}
3970
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003971
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003972static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003973{
3974 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003975 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3976 if(uError) {
3977 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003978 }
3979 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3980 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003981 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003982}
3983
3984
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003985static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003986{
3987 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003988 /* The negative integer furthest from zero for a C int64_t is
3989 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3990 negative number in CBOR is computed as -n - 1 where n is the
3991 encoded integer, where n is what is in the variable BigNum. When
3992 converting BigNum to a uint64_t, the maximum value is thus
3993 INT64_MAX, so that when it -n - 1 is applied to it the result will
3994 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003995
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003996 -n - 1 <= INT64_MIN.
3997 -n - 1 <= -INT64_MAX - 1
3998 n <= INT64_MAX.
3999 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004000 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004001 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004002 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004003 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004004
4005 /// Now apply -n - 1. The cast is safe because
4006 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4007 // is the largest positive integer that an int64_t can
4008 // represent. */
4009 *pnResult = -(int64_t)uResult - 1;
4010
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004011 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004012}
4013
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004014
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004015
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004016
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004017
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004018/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004019Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004020
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004021\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004022
Laurence Lundblade93d89472020-10-03 22:30:50 -07004023\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4024 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004025
4026\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4027
Laurence Lundblade93d89472020-10-03 22:30:50 -07004028\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4029 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004030*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004031static QCBORError
4032ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004033{
4034 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004035 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004036 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004037#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004039 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4040 http://www.cplusplus.com/reference/cmath/llround/
4041 */
4042 // Not interested in FE_INEXACT
4043 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004044 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4045 *pnValue = llround(pItem->val.dfnum);
4046 } else {
4047 *pnValue = lroundf(pItem->val.fnum);
4048 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004049 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4050 // llround() shouldn't result in divide by zero, but catch
4051 // it here in case it unexpectedly does. Don't try to
4052 // distinguish between the various exceptions because it seems
4053 // they vary by CPU, compiler and OS.
4054 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 }
4056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004058 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004059#else
4060 return QCBOR_ERR_HW_FLOAT_DISABLED;
4061#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004062 break;
4063
4064 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004066 *pnValue = pItem->val.int64;
4067 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069 }
4070 break;
4071
4072 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004073 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004074 if(pItem->val.uint64 < INT64_MAX) {
4075 *pnValue = pItem->val.int64;
4076 } else {
4077 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4078 }
4079 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004080 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081 }
4082 break;
4083
4084 default:
4085 return QCBOR_ERR_UNEXPECTED_TYPE;
4086 }
4087 return QCBOR_SUCCESS;
4088}
4089
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004090
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004091void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004094 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004095{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004096 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004097 return;
4098 }
4099
Laurence Lundbladee6430642020-03-14 21:15:44 -07004100 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004101 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4102 if(uError) {
4103 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004104 return;
4105 }
4106
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004107 if(pItem) {
4108 *pItem = Item;
4109 }
4110
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112}
4113
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004114
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004115void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4116 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004117 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004118 int64_t *pnValue,
4119 QCBORItem *pItem)
4120{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004121 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004122 if(pMe->uLastError != QCBOR_SUCCESS) {
4123 return;
4124 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004125
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004126 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127}
4128
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004129
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004130void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4131 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004132 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004133 int64_t *pnValue,
4134 QCBORItem *pItem)
4135{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004136 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004137 if(pMe->uLastError != QCBOR_SUCCESS) {
4138 return;
4139 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004142}
4143
4144
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004145/*
4146 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004147
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004148 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149
Laurence Lundblade93d89472020-10-03 22:30:50 -07004150 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4151 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004152
4153 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4154
Laurence Lundblade93d89472020-10-03 22:30:50 -07004155 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4156 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004157 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004158static QCBORError
4159Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004161 switch(pItem->uDataType) {
4162
4163 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004165 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004166 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004167 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004168 }
4169 break;
4170
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004171 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004172 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004173 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004174 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004175 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004176 }
4177 break;
4178
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004179#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4180 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004182 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004183 pItem->val.expAndMantissa.nExponent,
4184 pnValue,
4185 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004186 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004187 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004188 }
4189 break;
4190
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004191 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004193 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004194 pItem->val.expAndMantissa.nExponent,
4195 pnValue,
4196 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004197 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004198 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004199 }
4200 break;
4201
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004202 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004203 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004204 int64_t nMantissa;
4205 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004206 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4207 if(uErr) {
4208 return uErr;
4209 }
4210 return ExponentiateNN(nMantissa,
4211 pItem->val.expAndMantissa.nExponent,
4212 pnValue,
4213 Exponentitate10);
4214 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004216 }
4217 break;
4218
4219 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004221 int64_t nMantissa;
4222 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004223 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4224 if(uErr) {
4225 return uErr;
4226 }
4227 return ExponentiateNN(nMantissa,
4228 pItem->val.expAndMantissa.nExponent,
4229 pnValue,
4230 Exponentitate10);
4231 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004232 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004233 }
4234 break;
4235
4236 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004237 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004238 int64_t nMantissa;
4239 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4241 if(uErr) {
4242 return uErr;
4243 }
4244 return ExponentiateNN(nMantissa,
4245 pItem->val.expAndMantissa.nExponent,
4246 pnValue,
4247 Exponentitate2);
4248 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004249 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004250 }
4251 break;
4252
4253 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004254 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004255 int64_t nMantissa;
4256 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4258 if(uErr) {
4259 return uErr;
4260 }
4261 return ExponentiateNN(nMantissa,
4262 pItem->val.expAndMantissa.nExponent,
4263 pnValue,
4264 Exponentitate2);
4265 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004266 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004267 }
4268 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004269#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4270
Laurence Lundbladee6430642020-03-14 21:15:44 -07004271
Laurence Lundbladec4537442020-04-14 18:53:22 -07004272 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004273 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004274}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004275
4276
Laurence Lundbladec4537442020-04-14 18:53:22 -07004277/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004278 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004280void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004281{
4282 QCBORItem Item;
4283
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004284 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004285
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004286 if(pMe->uLastError == QCBOR_SUCCESS) {
4287 // The above conversion succeeded
4288 return;
4289 }
4290
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004291 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004292 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004293 return;
4294 }
4295
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004296 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004297}
4298
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004299
4300/*
4301Public function, see header qcbor/qcbor_decode.h file
4302*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4304 int64_t nLabel,
4305 uint32_t uConvertTypes,
4306 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004307{
4308 QCBORItem Item;
4309
Laurence Lundblade93d89472020-10-03 22:30:50 -07004310 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4311 nLabel,
4312 uConvertTypes,
4313 pnValue,
4314 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004315
4316 if(pMe->uLastError == QCBOR_SUCCESS) {
4317 // The above conversion succeeded
4318 return;
4319 }
4320
4321 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4322 // The above conversion failed in a way that code below can't correct
4323 return;
4324 }
4325
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004326 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004327}
4328
4329
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004330/*
4331Public function, see header qcbor/qcbor_decode.h file
4332*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004333void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4334 const char *szLabel,
4335 uint32_t uConvertTypes,
4336 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004337{
4338 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004339 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4340 szLabel,
4341 uConvertTypes,
4342 pnValue,
4343 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004344
4345 if(pMe->uLastError == QCBOR_SUCCESS) {
4346 // The above conversion succeeded
4347 return;
4348 }
4349
4350 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4351 // The above conversion failed in a way that code below can't correct
4352 return;
4353 }
4354
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004355 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004356}
4357
4358
Laurence Lundblade93d89472020-10-03 22:30:50 -07004359static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360{
4361 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004362 case QCBOR_TYPE_DOUBLE:
4363 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004364#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004365 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004366 // Can't use llround here because it will not convert values
4367 // greater than INT64_MAX and less than UINT64_MAX that
4368 // need to be converted so it is more complicated.
4369 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4370 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4371 if(isnan(pItem->val.dfnum)) {
4372 return QCBOR_ERR_FLOAT_EXCEPTION;
4373 } else if(pItem->val.dfnum < 0) {
4374 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4375 } else {
4376 double dRounded = round(pItem->val.dfnum);
4377 // See discussion in DecodeDateEpoch() for
4378 // explanation of - 0x7ff
4379 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4380 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4381 }
4382 *puValue = (uint64_t)dRounded;
4383 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004384 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004385 if(isnan(pItem->val.fnum)) {
4386 return QCBOR_ERR_FLOAT_EXCEPTION;
4387 } else if(pItem->val.fnum < 0) {
4388 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4389 } else {
4390 float fRounded = roundf(pItem->val.fnum);
4391 // See discussion in DecodeDateEpoch() for
4392 // explanation of - 0x7ff
4393 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4394 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4395 }
4396 *puValue = (uint64_t)fRounded;
4397 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004398 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004399 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4400 // round() and roundf() shouldn't result in exceptions here, but
4401 // catch them to be robust and thorough. Don't try to
4402 // distinguish between the various exceptions because it seems
4403 // they vary by CPU, compiler and OS.
4404 return QCBOR_ERR_FLOAT_EXCEPTION;
4405 }
4406
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004407 } else {
4408 return QCBOR_ERR_UNEXPECTED_TYPE;
4409 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004410#else
4411 return QCBOR_ERR_HW_FLOAT_DISABLED;
4412#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004413 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004414
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004415 case QCBOR_TYPE_INT64:
4416 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4417 if(pItem->val.int64 >= 0) {
4418 *puValue = (uint64_t)pItem->val.int64;
4419 } else {
4420 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4421 }
4422 } else {
4423 return QCBOR_ERR_UNEXPECTED_TYPE;
4424 }
4425 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004427 case QCBOR_TYPE_UINT64:
4428 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4429 *puValue = pItem->val.uint64;
4430 } else {
4431 return QCBOR_ERR_UNEXPECTED_TYPE;
4432 }
4433 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004435 default:
4436 return QCBOR_ERR_UNEXPECTED_TYPE;
4437 }
4438
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004439 return QCBOR_SUCCESS;
4440}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004441
4442
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004443void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004444 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004446 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004447{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004448 if(pMe->uLastError != QCBOR_SUCCESS) {
4449 return;
4450 }
4451
Laurence Lundbladec4537442020-04-14 18:53:22 -07004452 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004453
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004454 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4455 if(uError) {
4456 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004457 return;
4458 }
4459
Laurence Lundbladea826c502020-05-10 21:07:00 -07004460 if(pItem) {
4461 *pItem = Item;
4462 }
4463
Laurence Lundblade93d89472020-10-03 22:30:50 -07004464 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004465}
4466
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004467
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004468void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004470 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471 uint64_t *puValue,
4472 QCBORItem *pItem)
4473{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004474 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004475 if(pMe->uLastError != QCBOR_SUCCESS) {
4476 return;
4477 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004478
Laurence Lundblade93d89472020-10-03 22:30:50 -07004479 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004480}
4481
4482
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004483void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004485 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004486 uint64_t *puValue,
4487 QCBORItem *pItem)
4488{
4489 if(pMe->uLastError != QCBOR_SUCCESS) {
4490 return;
4491 }
4492
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004493 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004494 if(pMe->uLastError != QCBOR_SUCCESS) {
4495 return;
4496 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497
Laurence Lundblade93d89472020-10-03 22:30:50 -07004498 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499}
4500
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004501
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004502
Laurence Lundblade93d89472020-10-03 22:30:50 -07004503static QCBORError
4504UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004505{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 switch(pItem->uDataType) {
4507
4508 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004509 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004510 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4511 } 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_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004517 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004518 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4519 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004520 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 }
4522 break;
4523
4524#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4525
4526 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004527 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004528 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529 pItem->val.expAndMantissa.nExponent,
4530 puValue,
4531 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004532 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004533 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 }
4535 break;
4536
4537 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004538 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004539 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4540 pItem->val.expAndMantissa.nExponent,
4541 puValue,
4542 Exponentitate2);
4543 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004544 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004545 }
4546 break;
4547
4548 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004550 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004551 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004552 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553 if(uErr != QCBOR_SUCCESS) {
4554 return uErr;
4555 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004556 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557 pItem->val.expAndMantissa.nExponent,
4558 puValue,
4559 Exponentitate10);
4560 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004561 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004562 }
4563 break;
4564
4565 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004566 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4568 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004569 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004570 }
4571 break;
4572
4573 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004574 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004575 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004576 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004577 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004578 if(uErr != QCBOR_SUCCESS) {
4579 return uErr;
4580 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004581 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004582 pItem->val.expAndMantissa.nExponent,
4583 puValue,
4584 Exponentitate2);
4585 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004586 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004587 }
4588 break;
4589
4590 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004591 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004592 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4593 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004594 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595 }
4596 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004597#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 default:
4599 return QCBOR_ERR_UNEXPECTED_TYPE;
4600 }
4601}
4602
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004603
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004604/*
4605 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004606 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004608{
4609 QCBORItem Item;
4610
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004611 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004612
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004613 if(pMe->uLastError == QCBOR_SUCCESS) {
4614 // The above conversion succeeded
4615 return;
4616 }
4617
4618 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4619 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004620 return;
4621 }
4622
Laurence Lundblade93d89472020-10-03 22:30:50 -07004623 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004624}
4625
Laurence Lundbladec4537442020-04-14 18:53:22 -07004626
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004627/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004628 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004630void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004631 int64_t nLabel,
4632 uint32_t uConvertTypes,
4633 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004634{
4635 QCBORItem Item;
4636
Laurence Lundblade93d89472020-10-03 22:30:50 -07004637 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4638 nLabel,
4639 uConvertTypes,
4640 puValue,
4641 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642
4643 if(pMe->uLastError == QCBOR_SUCCESS) {
4644 // The above conversion succeeded
4645 return;
4646 }
4647
4648 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4649 // The above conversion failed in a way that code below can't correct
4650 return;
4651 }
4652
Laurence Lundblade93d89472020-10-03 22:30:50 -07004653 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004654}
4655
4656
4657/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004658 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004659*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004660void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004661 const char *szLabel,
4662 uint32_t uConvertTypes,
4663 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004664{
4665 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004666 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4667 szLabel,
4668 uConvertTypes,
4669 puValue,
4670 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671
4672 if(pMe->uLastError == QCBOR_SUCCESS) {
4673 // The above conversion succeeded
4674 return;
4675 }
4676
4677 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4678 // The above conversion failed in a way that code below can't correct
4679 return;
4680 }
4681
Laurence Lundblade93d89472020-10-03 22:30:50 -07004682 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004683}
4684
4685
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004686
4687
Laurence Lundblade9b334962020-08-27 10:55:53 -07004688static QCBORError ConvertDouble(const QCBORItem *pItem,
4689 uint32_t uConvertTypes,
4690 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004691{
4692 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004693 case QCBOR_TYPE_FLOAT:
4694#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4695 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4696 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004697 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004698 *pdValue = (double)pItem->val.fnum;
4699 } else {
4700 return QCBOR_ERR_UNEXPECTED_TYPE;
4701 }
4702 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004703#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004704 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004705#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004706 break;
4707
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004708 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4710 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711 *pdValue = pItem->val.dfnum;
4712 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004713 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714 }
4715 }
4716 break;
4717
4718 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004719#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004721 // A simple cast seems to do the job with no worry of exceptions.
4722 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723 *pdValue = (double)pItem->val.int64;
4724
4725 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004728#else
4729 return QCBOR_ERR_HW_FLOAT_DISABLED;
4730#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004731 break;
4732
4733 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004734#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004736 // A simple cast seems to do the job with no worry of exceptions.
4737 // There will be precision loss for some values.
4738 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004739 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004740 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741 }
4742 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004743#else
4744 return QCBOR_ERR_HW_FLOAT_DISABLED;
4745#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746
4747 default:
4748 return QCBOR_ERR_UNEXPECTED_TYPE;
4749 }
4750
4751 return QCBOR_SUCCESS;
4752}
4753
4754
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004755void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004758 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004759{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004760 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004761 return;
4762 }
4763
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004764 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004765
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004766 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004767 if(uError) {
4768 pMe->uLastError = (uint8_t)uError;
4769 return;
4770 }
4771
4772 if(pItem) {
4773 *pItem = Item;
4774 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004775
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004776 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004777}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004778
Laurence Lundbladec4537442020-04-14 18:53:22 -07004779
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004780void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4781 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783 double *pdValue,
4784 QCBORItem *pItem)
4785{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004786 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004787 if(pMe->uLastError != QCBOR_SUCCESS) {
4788 return;
4789 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792}
4793
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004794
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4796 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798 double *pdValue,
4799 QCBORItem *pItem)
4800{
4801 if(pMe->uLastError != QCBOR_SUCCESS) {
4802 return;
4803 }
4804
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004805 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004806 if(pMe->uLastError != QCBOR_SUCCESS) {
4807 return;
4808 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004809
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004810 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004811}
4812
4813
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004814#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004815static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4816{
4817 double dResult;
4818
4819 dResult = 0.0;
4820 const uint8_t *pByte = BigNum.ptr;
4821 size_t uLen = BigNum.len;
4822 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004823 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004824 while(uLen--) {
4825 dResult = (dResult * 256.0) + (double)*pByte++;
4826 }
4827
4828 return dResult;
4829}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004830#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4831
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004832
Laurence Lundblade93d89472020-10-03 22:30:50 -07004833static QCBORError
4834DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004835{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004836#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004837 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004838 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4839
4840 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004842
4843#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004846 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4848 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4849 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004850 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004851 }
4852 break;
4853
4854 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004855 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004856 // Underflow gives 0, overflow gives infinity
4857 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4858 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004860 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861 }
4862 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004863#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004864
4865 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4868 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004869 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870 }
4871 break;
4872
4873 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004874 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004875 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004877 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004878 }
4879 break;
4880
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004881#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004883 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4885 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4886 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004887 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004888 }
4889 break;
4890
4891 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004892 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4894 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4895 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004896 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004897 }
4898 break;
4899
4900 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4903 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4904 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906 }
4907 break;
4908
4909 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004910 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004911 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4913 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004914 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004915 }
4916 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004917#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4918
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004919 default:
4920 return QCBOR_ERR_UNEXPECTED_TYPE;
4921 }
4922
4923 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004924
4925#else
4926 (void)pItem;
4927 (void)uConvertTypes;
4928 (void)pdValue;
4929 return QCBOR_ERR_HW_FLOAT_DISABLED;
4930#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4931
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004932}
4933
4934
4935/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004936 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004937*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004938void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4939 uint32_t uConvertTypes,
4940 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004941{
4942
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004943 QCBORItem Item;
4944
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004945 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004946
4947 if(pMe->uLastError == QCBOR_SUCCESS) {
4948 // The above conversion succeeded
4949 return;
4950 }
4951
4952 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4953 // The above conversion failed in a way that code below can't correct
4954 return;
4955 }
4956
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004957 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004958}
4959
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960
4961/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004962 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004964void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4965 int64_t nLabel,
4966 uint32_t uConvertTypes,
4967 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004968{
4969 QCBORItem Item;
4970
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004971 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004972
4973 if(pMe->uLastError == QCBOR_SUCCESS) {
4974 // The above conversion succeeded
4975 return;
4976 }
4977
4978 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4979 // The above conversion failed in a way that code below can't correct
4980 return;
4981 }
4982
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004983 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004984}
4985
4986
4987/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004988 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004989*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004990void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4991 const char *szLabel,
4992 uint32_t uConvertTypes,
4993 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004994{
4995 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004996 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004997
4998 if(pMe->uLastError == QCBOR_SUCCESS) {
4999 // The above conversion succeeded
5000 return;
5001 }
5002
5003 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5004 // The above conversion failed in a way that code below can't correct
5005 return;
5006 }
5007
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005008 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005009}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005010
5011
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005012
5013
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005014#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005015static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5016{
5017 while((uInt & 0xff00000000000000UL) == 0) {
5018 uInt = uInt << 8;
5019 };
5020
5021 UsefulOutBuf UOB;
5022
5023 UsefulOutBuf_Init(&UOB, Buffer);
5024
5025 while(uInt) {
5026 const uint64_t xx = uInt & 0xff00000000000000UL;
5027 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5028 uInt = uInt << 8;
5029 (void)xx;
5030 }
5031
5032 return UsefulOutBuf_OutUBuf(&UOB);
5033}
5034
5035
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005036static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5037 TagSpecification TagSpec,
5038 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005039{
5040 QCBORError uErr;
5041 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005042 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005043 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005044 if(uErr != QCBOR_SUCCESS) {
5045 goto Done;
5046 }
5047
5048 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5049 break; // Successful exit. Moving on to finish decoding.
5050 }
5051
5052 // The item is an array, which means an undecoded
5053 // mantissa and exponent, so decode it. It will then
5054 // have a different type and exit the loop if.
5055 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5056 if(uErr != QCBOR_SUCCESS) {
5057 goto Done;
5058 }
5059
5060 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005061 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005062 }
5063Done:
5064 return uErr;
5065}
5066
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005067
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005068static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005069 TagSpecification TagSpec,
5070 QCBORItem *pItem,
5071 int64_t *pnMantissa,
5072 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005073{
5074 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005076 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005077 if(uErr != QCBOR_SUCCESS) {
5078 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005079 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005080
Laurence Lundblade9b334962020-08-27 10:55:53 -07005081 switch (pItem->uDataType) {
5082
5083 case QCBOR_TYPE_DECIMAL_FRACTION:
5084 case QCBOR_TYPE_BIGFLOAT:
5085 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5086 *pnExponent = pItem->val.expAndMantissa.nExponent;
5087 break;
5088
5089 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5090 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5091 *pnExponent = pItem->val.expAndMantissa.nExponent;
5092 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5093 break;
5094
5095 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5096 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5097 *pnExponent = pItem->val.expAndMantissa.nExponent;
5098 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5099 break;
5100
5101 default:
5102 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5103 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005104
5105 Done:
5106 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005107}
5108
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005109
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005110static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005111 TagSpecification TagSpec,
5112 QCBORItem *pItem,
5113 UsefulBuf BufferForMantissa,
5114 UsefulBufC *pMantissa,
5115 bool *pbIsNegative,
5116 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005117{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005118 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005119
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005120 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005121 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005122 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005123 }
5124
5125 uint64_t uMantissa;
5126
5127 switch (pItem->uDataType) {
5128
5129 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005130 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005131 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5132 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5133 *pbIsNegative = false;
5134 } else {
5135 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5136 *pbIsNegative = true;
5137 }
5138 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5139 *pnExponent = pItem->val.expAndMantissa.nExponent;
5140 break;
5141
5142 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005143 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005144 *pnExponent = pItem->val.expAndMantissa.nExponent;
5145 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5146 *pbIsNegative = false;
5147 break;
5148
5149 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005150 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005151 *pnExponent = pItem->val.expAndMantissa.nExponent;
5152 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5153 *pbIsNegative = true;
5154 break;
5155
5156 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005157 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005158 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005159
5160Done:
5161 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005162}
5163
5164
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005165/*
5166 Public function, see header qcbor/qcbor_decode.h file
5167*/
5168void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5169 uint8_t uTagRequirement,
5170 int64_t *pnMantissa,
5171 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005172{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005173 if(pMe->uLastError != QCBOR_SUCCESS) {
5174 return;
5175 }
5176
5177 QCBORItem Item;
5178 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5179 if(uError) {
5180 pMe->uLastError = (uint8_t)uError;
5181 return;
5182 }
5183
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184 const TagSpecification TagSpec =
5185 {
5186 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005187 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5188 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5189 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005191
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005192 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005193}
5194
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005195
5196/*
5197 Public function, see header qcbor/qcbor_decode.h file
5198*/
5199void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005200 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005201 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005202 int64_t *pnMantissa,
5203 int64_t *pnExponent)
5204{
5205 if(pMe->uLastError != QCBOR_SUCCESS) {
5206 return;
5207 }
5208
5209 QCBORItem Item;
5210 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5211
5212 const TagSpecification TagSpec =
5213 {
5214 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005215 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5216 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5217 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005218 };
5219
5220 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5221}
5222
5223
5224/*
5225 Public function, see header qcbor/qcbor_decode.h file
5226*/
5227void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005228 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005229 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230 int64_t *pnMantissa,
5231 int64_t *pnExponent)
5232{
5233 if(pMe->uLastError != QCBOR_SUCCESS) {
5234 return;
5235 }
5236
5237 QCBORItem Item;
5238 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5239
5240 const TagSpecification TagSpec =
5241 {
5242 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005243 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5244 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5245 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005246 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005247
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005248 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5249}
5250
5251
5252/*
5253 Public function, see header qcbor/qcbor_decode.h file
5254*/
5255void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5256 uint8_t uTagRequirement,
5257 UsefulBuf MantissaBuffer,
5258 UsefulBufC *pMantissa,
5259 bool *pbMantissaIsNegative,
5260 int64_t *pnExponent)
5261{
5262 if(pMe->uLastError != QCBOR_SUCCESS) {
5263 return;
5264 }
5265
5266 QCBORItem Item;
5267 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5268 if(uError) {
5269 pMe->uLastError = (uint8_t)uError;
5270 return;
5271 }
5272
5273 const TagSpecification TagSpec =
5274 {
5275 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005276 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5277 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5278 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005279 };
5280
Laurence Lundblade93d89472020-10-03 22:30:50 -07005281 ProcessMantissaAndExponentBig(pMe,
5282 TagSpec,
5283 &Item,
5284 MantissaBuffer,
5285 pMantissa,
5286 pbMantissaIsNegative,
5287 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005288}
5289
5290
5291/*
5292 Public function, see header qcbor/qcbor_decode.h file
5293*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005294void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005295 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005296 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005297 UsefulBuf BufferForMantissa,
5298 UsefulBufC *pMantissa,
5299 bool *pbIsNegative,
5300 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005301{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005302 if(pMe->uLastError != QCBOR_SUCCESS) {
5303 return;
5304 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005305
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005306 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005307 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005308 if(pMe->uLastError != QCBOR_SUCCESS) {
5309 return;
5310 }
5311
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005312 const TagSpecification TagSpec =
5313 {
5314 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005315 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5316 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5317 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005319
Laurence Lundblade93d89472020-10-03 22:30:50 -07005320 ProcessMantissaAndExponentBig(pMe,
5321 TagSpec,
5322 &Item,
5323 BufferForMantissa,
5324 pMantissa,
5325 pbIsNegative,
5326 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005327}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005328
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005329
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005330/*
5331 Public function, see header qcbor/qcbor_decode.h file
5332*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005333void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005334 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005335 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005336 UsefulBuf BufferForMantissa,
5337 UsefulBufC *pMantissa,
5338 bool *pbIsNegative,
5339 int64_t *pnExponent)
5340{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 if(pMe->uLastError != QCBOR_SUCCESS) {
5342 return;
5343 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005344
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005345 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005346 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5347 if(pMe->uLastError != QCBOR_SUCCESS) {
5348 return;
5349 }
5350
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005351 const TagSpecification TagSpec =
5352 {
5353 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005354 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5355 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5356 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005357 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005358
5359 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5360}
5361
5362
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005363/*
5364 Public function, see header qcbor/qcbor_decode.h file
5365*/
5366void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5367 uint8_t uTagRequirement,
5368 int64_t *pnMantissa,
5369 int64_t *pnExponent)
5370{
5371 if(pMe->uLastError != QCBOR_SUCCESS) {
5372 return;
5373 }
5374
5375 QCBORItem Item;
5376 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5377 if(uError) {
5378 pMe->uLastError = (uint8_t)uError;
5379 return;
5380 }
5381 const TagSpecification TagSpec =
5382 {
5383 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005384 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5385 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5386 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005387 };
5388
5389 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5390}
5391
5392
5393/*
5394 Public function, see header qcbor/qcbor_decode.h file
5395*/
5396void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005397 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005398 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399 int64_t *pnMantissa,
5400 int64_t *pnExponent)
5401{
5402 if(pMe->uLastError != QCBOR_SUCCESS) {
5403 return;
5404 }
5405
5406 QCBORItem Item;
5407 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5408 if(pMe->uLastError != QCBOR_SUCCESS) {
5409 return;
5410 }
5411
5412 const TagSpecification TagSpec =
5413 {
5414 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005415 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5416 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5417 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005418 };
5419
5420 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5421}
5422
5423
5424/*
5425 Public function, see header qcbor/qcbor_decode.h file
5426*/
5427void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005428 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005429 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005430 int64_t *pnMantissa,
5431 int64_t *pnExponent)
5432{
5433 if(pMe->uLastError != QCBOR_SUCCESS) {
5434 return;
5435 }
5436
5437 QCBORItem Item;
5438 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5439 if(pMe->uLastError != QCBOR_SUCCESS) {
5440 return;
5441 }
5442
5443 const TagSpecification TagSpec =
5444 {
5445 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005446 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5447 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5448 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005449 };
5450
5451 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5452}
5453
5454
5455/*
5456 Public function, see header qcbor/qcbor_decode.h file
5457*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005458void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5459 uint8_t uTagRequirement,
5460 UsefulBuf MantissaBuffer,
5461 UsefulBufC *pMantissa,
5462 bool *pbMantissaIsNegative,
5463 int64_t *pnExponent)
5464{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005465 if(pMe->uLastError != QCBOR_SUCCESS) {
5466 return;
5467 }
5468
5469 QCBORItem Item;
5470 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5471 if(uError) {
5472 pMe->uLastError = (uint8_t)uError;
5473 return;
5474 }
5475
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476 const TagSpecification TagSpec =
5477 {
5478 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005479 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5480 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5481 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005483
5484 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005485}
5486
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005487
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488/*
5489 Public function, see header qcbor/qcbor_decode.h file
5490*/
5491void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005492 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005493 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005494 UsefulBuf BufferForMantissa,
5495 UsefulBufC *pMantissa,
5496 bool *pbIsNegative,
5497 int64_t *pnExponent)
5498{
5499 if(pMe->uLastError != QCBOR_SUCCESS) {
5500 return;
5501 }
5502
5503 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005504 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5505 if(pMe->uLastError != QCBOR_SUCCESS) {
5506 return;
5507 }
5508
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005509 const TagSpecification TagSpec =
5510 {
5511 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005512 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5513 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5514 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005515 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005516
Laurence Lundblade93d89472020-10-03 22:30:50 -07005517 ProcessMantissaAndExponentBig(pMe,
5518 TagSpec,
5519 &Item,
5520 BufferForMantissa,
5521 pMantissa,
5522 pbIsNegative,
5523 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005524}
5525
5526
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005527/*
5528 Public function, see header qcbor/qcbor_decode.h file
5529*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005530void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005531 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005532 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005533 UsefulBuf BufferForMantissa,
5534 UsefulBufC *pMantissa,
5535 bool *pbIsNegative,
5536 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005537{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005538 if(pMe->uLastError != QCBOR_SUCCESS) {
5539 return;
5540 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005541
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005542 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005543 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5544 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005545 return;
5546 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005547
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005548 const TagSpecification TagSpec =
5549 {
5550 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005551 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5552 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5553 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005554 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005555
Laurence Lundblade93d89472020-10-03 22:30:50 -07005556 ProcessMantissaAndExponentBig(pMe,
5557 TagSpec,
5558 &Item,
5559 BufferForMantissa,
5560 pMantissa,
5561 pbIsNegative,
5562 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005563}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005564
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005565#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */