blob: 20dc83ef9243d6b80146f9582aa019ad2860c068 [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 Lundbladea3336842021-01-03 12:38:36 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence 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 Lundblade25403ed2021-01-02 16:28:07 -0800556void QCBORDecode_Init(QCBORDecodeContext *pMe,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800560 memset(pMe, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(pMe->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 Lundblade25403ed2021-01-02 16:28:07 -0800565 pMe->uDecodeMode = (uint8_t)nDecodeMode;
566 DecodeNesting_Init(&(pMe->nesting));
567
568 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
569 * GetNext_TaggedItem() and MapTagNumber(). */
570 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571}
572
573
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800574#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
575
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800577 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700578 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800579void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
580 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800581 void *pAllocateContext,
582 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700583{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800584 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
585 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
586 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700587}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800588#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800590
Laurence Lundblade6474c982020-12-26 22:14:34 -0800591
592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800594 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800595 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800596void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700598{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800599 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700600 (void)pMe;
601 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602}
603
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800605
606
607/*
608 Decoding items is done in 5 layered functions, one calling the
609 next one down. If a layer has no work to do for a particular item
610 it returns quickly.
611
612 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
613 tagged data items, turning them into the local C representation.
614 For the most simple it is just associating a QCBOR_TYPE with the data. For
615 the complex ones that an aggregate of data items, there is some further
616 decoding and a little bit of recursion.
617
618 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
619 ends of maps and arrays. It tracks descending into and ascending
620 out of maps/arrays. It processes all breaks that terminate
621 indefinite length maps and arrays.
622
623 - GetNext_MapEntry -- This handles the combining of two
624 items, the label and the data, that make up a map entry.
625 It only does work on maps. It combines the label and data
626 items into one labeled item.
627
628 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
629 tags into bit flags associated with the data item. No actual decoding
630 of the contents of the tagged item is performed here.
631
632 - GetNext_FullItem -- This assembles the sub-items that make up
633 an indefinte length string into one string item. It uses the
634 string allocater to create contiguous space for the item. It
635 processes all breaks that are part of indefinite length strings.
636
637 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
638 atomic data item has a "major type", an integer "argument" and optionally
639 some content. For text and byte strings, the content is the bytes
640 that make up the string. These are the smallest data items that are
641 considered to be well-formed. The content may also be other data items in
642 the case of aggregate types. They are not handled in this layer.
643
644 Roughly this takes 300 bytes of stack for vars. Need to
645 evaluate this more carefully and correctly.
646
647 */
648
649
Laurence Lundblade1c929722020-12-27 02:44:57 -0800650/**
651 * @brief Decode the CBOR head, the type and argument.
652 *
653 * @param[in] pUInBuf The input buffer to read from.
654 * @param[out] pnMajorType The decoded major type.
655 * @param[out] puArgument The decoded argument.
656 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
657 *
658 * @retval QCBOR_ERR_UNSUPPORTED
659 * @retval QCBOR_ERR_HIT_END
660 *
661 * This decodes the CBOR "head" that every CBOR data item has. See
662 * longer explaination of the head in documentation for
663 * QCBOREncode_EncodeHead().
664 *
665 * This does the network->host byte order conversion. The conversion
666 * here also results in the conversion for floats in addition to that
667 * for lengths, tags and integer values.
668 *
669 * The int type is preferred to uint8_t for some variables as this
670 * avoids integer promotions, can reduce code size and makes static
671 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800673static inline QCBORError
674DecodeHead(UsefulInputBuf *pUInBuf,
675 int *pnMajorType,
676 uint64_t *puArgument,
677 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800679 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800680
Laurence Lundblade1c929722020-12-27 02:44:57 -0800681 /* Get the initial byte that every CBOR data item has and break it
682 * down. */
683 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684 const int nTmpMajorType = nInitialByte >> 5;
685 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800686
Laurence Lundblade1c929722020-12-27 02:44:57 -0800687 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800688 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800690 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800691 /* Need to get 1,2,4 or 8 additional argument bytes. Map
692 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
693 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800694 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundblade1c929722020-12-27 02:44:57 -0800696 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800697 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800698 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800699 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800700 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
701 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800702 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800703 /* The reserved and thus-far unused additional info values */
704 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800705 goto Done;
706 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800707 /* Less than 24, additional info is argument or 31, an
708 * indefinite length. No more bytes to get.
709 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800710 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800712
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800714 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 goto Done;
716 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800717
Laurence Lundblade1c929722020-12-27 02:44:57 -0800718 /* All successful if arrived here. */
719 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800720 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800721 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800725 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726}
727
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800728
Laurence Lundblade1c929722020-12-27 02:44:57 -0800729/**
730 * @brief Decode integer types, major types 0 and 1.
731 *
732 * @param[in] nMajorType The CBOR major type (0 or 1).
733 * @param[in] uArgument The argument from the head.
734 * @param[out] pDecodedItem The filled in decoded item.
735 *
736 * @retval QCBOR_ERR_INT_OVERFLOW
737 *
738 * Must only be called when major type is 0 or 1.
739 *
740 * CBOR doesn't explicitly specify two's compliment for integers but
741 * all CPUs use it these days and the test vectors in the RFC are
742 * so. All integers in the CBOR structure are positive and the major
743 * type indicates positive or negative. CBOR can express positive
744 * integers up to 2^x - 1 where x is the number of bits and negative
745 * integers down to 2^x. Note that negative numbers can be one more
746 * away from zero than positive. Stdint, as far as I can tell, uses
747 * two's compliment to represent negative integers.
748 *
749 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
750 * used carefully here, and in particular why it isn't used in the
751 * public interface. Also see
752 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
753 *
754 * Int is used for values that need less than 16-bits and would be
755 * subject to integer promotion and result in complaining from static
756 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700758static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800759DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800761 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800762
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800764 if (uArgument <= INT64_MAX) {
765 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700766 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800769 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800774 if(uArgument <= INT64_MAX) {
775 /* CBOR's representation of negative numbers lines up with
776 * the two-compliment representation. A negative integer has
777 * one more in range than a positive integer. INT64_MIN is
778 * equal to (-INT64_MAX) - 1.
779 */
780 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800784 /* C can't represent a negative integer in this range so it
785 * is an error.
786 */
787 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 }
789 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundblade1c929722020-12-27 02:44:57 -0800791 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792}
793
Laurence Lundblade1c929722020-12-27 02:44:57 -0800794
Laurence Lundblade38299092020-12-28 04:13:50 -0800795/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
797#error QCBOR_TYPE_FALSE macro value wrong
798#endif
799
800#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
801#error QCBOR_TYPE_TRUE macro value wrong
802#endif
803
804#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
805#error QCBOR_TYPE_NULL macro value wrong
806#endif
807
808#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
809#error QCBOR_TYPE_UNDEF macro value wrong
810#endif
811
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700812#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
813#error QCBOR_TYPE_BREAK macro value wrong
814#endif
815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
817#error QCBOR_TYPE_DOUBLE macro value wrong
818#endif
819
820#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
821#error QCBOR_TYPE_FLOAT macro value wrong
822#endif
823
Laurence Lundblade38299092020-12-28 04:13:50 -0800824
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800825/**
826 * @brief Decode type 7 -- true, false, floating-point, break...
827 *
828 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
829 * @param[in] uArgument The argument from the head.
830 * @param[out] pDecodedItem The filled in decoded item.
831 *
832 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
833 * @retval QCBOR_ERR_BAD_TYPE_7
834 */
Laurence Lundblade9b334962020-08-27 10:55:53 -0700835
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700836static inline QCBORError
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800837DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838{
Laurence Lundblade38299092020-12-28 04:13:50 -0800839 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundblade38299092020-12-28 04:13:50 -0800841 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
842 * checks above make sure uAdditionalInfo values line up with
843 * uDataType values. DecodeHead() never returns an AdditionalInfo
844 * > 0x1f so cast is safe.
845 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800849 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
850 * are caught before this is called.
851 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundblade38299092020-12-28 04:13:50 -0800853 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700854#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800855 /* Half-precision is returned as a double. The cast to
856 * uint16_t is safe because the encoded value was 16 bits. It
857 * was widened to 64 bits to be passed in here.
858 */
859 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700860 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800861#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800862 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700864 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800865 case SINGLE_PREC_FLOAT: /* 26 */
866 /* Single precision is normally returned as a double since
867 * double is widely supported, there is no loss of precision,
868 * it makes it easy for the caller in most cases and it can
869 * be converted back to single with no loss of precision
870 *
871 * The cast to uint32_t is safe because the encoded value was
872 * 32 bits. It was widened to 64 bits to be passed in here.
873 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700874 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800875 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800877 /* In the normal case, use HW to convert float to
878 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700879 pDecodedItem->val.dfnum = (double)f;
880 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800881#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800882 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 pDecodedItem->val.fnum = f;
884 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
885
Laurence Lundblade38299092020-12-28 04:13:50 -0800886 /* IEEE754_FloatToDouble() could be used here to return as
887 * a double, but it adds object code and most likely
888 * anyone disabling FLOAT HW use doesn't care about floats
889 * and wants to save object code.
890 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800891#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700892 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700893 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894
Laurence Lundblade38299092020-12-28 04:13:50 -0800895 case DOUBLE_PREC_FLOAT: /* 27 */
896 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700897 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700898 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundblade38299092020-12-28 04:13:50 -0800900 case CBOR_SIMPLEV_FALSE: /* 20 */
901 case CBOR_SIMPLEV_TRUE: /* 21 */
902 case CBOR_SIMPLEV_NULL: /* 22 */
903 case CBOR_SIMPLEV_UNDEF: /* 23 */
904 case CBOR_SIMPLE_BREAK: /* 31 */
905 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade38299092020-12-28 04:13:50 -0800907 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
908 if(uArgument <= CBOR_SIMPLE_BREAK) {
909 /* This takes out f8 00 ... f8 1f which should be encoded
910 * as e0 … f7
911 */
912 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700913 goto Done;
914 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800915 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade38299092020-12-28 04:13:50 -0800917 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800919 /* DecodeHead() will make uArgument equal to
920 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
921 * safe because the 2, 4 and 8 byte lengths of uNumber are in
922 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800924 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 break;
926 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700928Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800929 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930}
931
932
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800933/**
934 * @brief Decode text and byte strings
935 *
936 * @param[in] pAllocator The string allocator or NULL.
937 * @param[in] uStrLen The length of the string.
938 * @param[in] pUInBuf The surce from which to read the string's bytes.
939 * @param[out] pDecodedItem The filled in decoded item.
940 *
941 * @retval QCBOR_ERR_HIT_END
942 * @retval QCBOR_ERR_STRING_ALLOCATE
943 * @retval QCBOR_ERR_STRING_TOO_LONG
944 *
945 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
946 * pDecodedItem. If @c pAllocator is not NULL then memory for the
947 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800949static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800950DecodeBytes(const QCBORInternalAllocator *pAllocator,
951 uint64_t uStrLen,
952 UsefulInputBuf *pUInBuf,
953 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954{
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800955 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800957 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
958 * CPUs. This check makes the casts to size_t below safe.
959 *
960 * The max is 4 bytes less than the largest sizeof() so this can be
961 * tested by putting a SIZE_MAX length in the CBOR test input (no
962 * one will care the limit on strings is 4 bytes shorter).
963 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800965 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 goto Done;
967 }
968
969 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530970 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800971 /* Failed to get the bytes for this string item */
972 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530973 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530975
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800976#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800977 /* Note that this is not where allocation to coallsece
978 * indefinite-length strings is done. This is for when the caller
979 * has requested all strings be allocated. Disabling indefinite
980 * length strings also disables this allocate-all option.
981 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800982 if(pAllocator) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800983 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530985 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800986 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530987 goto Done;
988 }
989 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800990 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800991 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800993#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
994 (void)pAllocator;
995#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
996
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800997 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800998 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301000Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001001 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002}
1003
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001004
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001005/**
1006 * @brief Map the CBOR major types for strings to the QCBOR types.
1007 *
1008 * @param[in] nCBORMajorType The CBOR major type to convert.
1009 * @retturns QCBOR type number.
1010 *
1011 * This only works for the two string types.
1012 */
1013static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001014{
1015 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1016 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1017 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001019 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1020 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1021 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001022
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 return (uint8_t)(nCBORMajorType + 4);
1024}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025
1026
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001027/**
1028 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1029 *
1030 * @param[in] nCBORMajorType The CBOR major type to convert.
1031 * @retturns QCBOR type number.
1032 *
1033 * This only works for the two aggregate types.
1034 */
1035static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
1036{
1037 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1038 #error QCBOR_TYPE_ARRAY value not lined up with major type
1039 #endif
1040
1041 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1042 #error QCBOR_TYPE_MAP value not lined up with major type
1043 #endif
1044
1045 return (uint8_t)(nCBORMajorType);
1046}
1047
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001049/**
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001050 * @brief Decode a single primitive data item.
1051 *
1052 * @param[in] pUInBuf Input buffer to read data item from.
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001053 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001054 * @param[in] pAllocator The allocator to use for strings or NULL.
1055 *
1056 * @retval QCBOR_ERR_UNSUPPORTED
1057 * @retval QCBOR_ERR_HIT_END
1058 * @retval QCBOR_ERR_INT_OVERFLOW
1059 * @retval QCBOR_ERR_STRING_ALLOCATE
1060 * @retval QCBOR_ERR_STRING_TOO_LONG
1061 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1062 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001063 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001064 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001065 * This decodes the most primitive / atomic data item. It does
1066 * no combing of data items.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001067 */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001068static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
1069 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001070 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071{
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001072 QCBORError uReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001074 /* Get the major type and the argument. The argument could be
1075 * length of more bytes or the value depending on the major
1076 * type. nAdditionalInfo is an encoding of the length of the
1077 * uNumber and is needed to decode floats and doubles.
1078 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001079 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001080 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001081 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001082
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001083 memset(pDecodedItem, 0, sizeof(QCBORItem));
1084
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001085 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1086 if(uReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001087 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001088 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001089
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001090 /* At this point the major type and the argument are valid. We've
1091 * got the type and the argument that starts every CBOR data item.
1092 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001093 switch (nMajorType) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001094 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1095 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001096 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001097 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001098 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001099 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001100 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001102
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001103 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1104 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1105 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001106 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001107 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001108 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001109 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001110 }
1111 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001112
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001113 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1114 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001115 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001116 /* Indefinite-length string. */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001117#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001118 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001119#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001120 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001121 break;
1122#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001123 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001124 /* Definite-length string. */
1125 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1126 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1127 goto Done;
1128 }
1129 /* cast OK because of check above */
Laurence Lundblade1c929722020-12-27 02:44:57 -08001130 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001131 }
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001132 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001135 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001136 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001137 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001138 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001139 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001140 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001141 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001143
Laurence Lundbladeee851742020-01-08 08:37:05 -08001144 case CBOR_MAJOR_TYPE_SIMPLE:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001145 /* Major type 7: float, double, true, false, null... */
1146 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladeee851742020-01-08 08:37:05 -08001149 default:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001150 /* Never happens because DecodeHead() should never return > 7 */
1151 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001152 break;
1153 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001156 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001157}
1158
1159
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001160/**
1161 * @brief Process indefinite length strings
1162 *
1163 * @param[in] pMe Decoder context
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001164 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 *
1166 * @retval QCBOR_ERR_UNSUPPORTED
1167 * @retval QCBOR_ERR_HIT_END
1168 * @retval QCBOR_ERR_INT_OVERFLOW
1169 * @retval QCBOR_ERR_STRING_ALLOCATE
1170 * @retval QCBOR_ERR_STRING_TOO_LONG
1171 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1172 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001173 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001174 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1175 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001176 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001177 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001178 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001179 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001180 * If it is, this loops getting the subsequent chunk data items that
1181 * make up the string. The string allocator is used to make a
1182 * contiguous buffer for the chunks. When this completes @c
1183 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184 *
1185 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001187static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001188GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001190 /* Aproximate stack usage
1191 * 64-bit 32-bit
1192 * local vars 32 16
1193 * 2 UsefulBufs 32 16
1194 * QCBORItem 56 52
1195 * TOTAL 120 74
1196 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001197
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 /* The string allocator is used here for two purposes: 1)
1199 * coalescing the chunks of an indefinite length string, 2)
1200 * allocating storage for every string returned.
1201 *
1202 * The first use is below in this function. Indefinite length
1203 * strings cannot be processed at all without a string allocator.
1204 *
1205 * The second used is in DecodeBytes() which is called by
1206 * GetNext_Item() below. This second use unneccessary for most use
1207 * and only happens when requested in the call to
1208 * QCBORDecode_SetMemPool(). If the second use not requested then
1209 * NULL is passed for the string allocator to GetNext_Item().
1210 *
1211 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1212 * allocator altogether and thus both of these uses. It reduced the
1213 * decoder object code by about 400 bytes.
1214 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001215 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001218 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001219
1220 if(pMe->StringAllocator.pfAllocator) {
1221 pAllocator = &(pMe->StringAllocator);
1222 if(pMe->bStringAllocateAll) {
1223 pAllocatorForGetNext = pAllocator;
1224 }
1225 }
1226#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1227
1228 QCBORError uReturn;
1229 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1230 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001231 goto Done;
1232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001233
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001234 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001235 const uint8_t uStringType = pDecodedItem->uDataType;
1236 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001237 goto Done;
1238 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001239
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001240 /* Is this a string with an indefinite length? */
1241 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1242 goto Done;
1243 }
1244
1245#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1246 /* Can't do indefinite length strings without a string allocator */
1247 if(pAllocator == NULL) {
1248 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1249 goto Done;
1250 }
1251
1252 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001253 UsefulBufC FullString = NULLUsefulBufC;
1254
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001255 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001256 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001257 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001258 /* Pass a NULL string allocator to GetNext_Item() because the
1259 * individual string chunks in an indefinite length should not
1260 * be allocated. They are always copied in the the contiguous
1261 * buffer allocated here.
1262 */
1263 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1264 if(uReturn) {
1265 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001266 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001267
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001268 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001269 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001270 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001271 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301272 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001273 break;
1274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001276 /* All chunks must be of the same type, the type of the item
1277 * that introduces the indefinite length string. This also
1278 * catches errors where the chunk is not a string at all and an
1279 * indefinite length string inside an indefinite length string.
1280 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001281 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001282 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1283 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001284 break;
1285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001286
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001287 /* The first time throurgh FullString.ptr is NULL and this is
1288 * equivalent to StringAllocator_Allocate(). Subsequently it is
1289 * not NULL and a reallocation happens.
1290 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001291 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1292 UNCONST_POINTER(FullString.ptr),
1293 FullString.len + StringChunkItem.val.string.len);
1294
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001295 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001296 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001297 break;
1298 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001299
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001300 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001301 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001302 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001303
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001304 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1305 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001306 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001307 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001308#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1309 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1310#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001311
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001312Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001313 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314}
1315
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001317/**
1318 * @brief This converts a tag number to a shorter mapped value for storage.
1319 *
1320 * @param[in] pMe The decode context.
1321 * @param[in] uUnMappedTag The tag number to map
1322 * @param[out] puMappedTagNumer The stored tag number.
1323 *
1324 * @return error code.
1325 *
1326 * The main point of mapping tag numbers is make QCBORItem
1327 * smaller. With this mapping storage of 4 tags takes up 8
1328 * bytes. Without, it would take up 32 bytes.
1329 *
1330 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1331 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1332 *
1333 * See also UnMapTagNumber() and @ref QCBORItem.
1334 */
1335static inline QCBORError
1336MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1337{
1338 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1339 int uTagMapIndex;
1340 /* Is there room in the tag map, or is it in it already? */
1341 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1342 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1343 break;
1344 }
1345 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1346 break;
1347 }
1348 }
1349 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1350 return QCBOR_ERR_TOO_MANY_TAGS;
1351 }
1352
1353 /* Covers the cases where tag is new and were it is already in the map */
1354 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1355 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1356
1357 } else {
1358 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1359 }
1360
1361 return QCBOR_SUCCESS;
1362}
1363
1364
1365/**
1366 * @brief This converts a mapped tag number to the actual tag number.
1367 *
1368 * @param[in] pMe The decode context.
1369 * @param[in] uMappedTagNumber The stored tag number.
1370 *
1371 * @return The actual tag number is returned or
1372 * @ref CBOR_TAG_INVALID64 on error.
1373 *
1374 * This is the reverse of MapTagNumber()
1375 */
1376static uint64_t
1377UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1378{
1379 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1380 return uMappedTagNumber;
1381 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001382 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001383 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001384 /* This won't be negative because of code below in
1385 * MapTagNumber()
1386 */
1387 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1388 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001389 }
1390}
1391
Laurence Lundblade9b334962020-08-27 10:55:53 -07001392
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001393/**
1394 * @brief Aggregate all tags wrapping a data item.
1395 *
1396 * @param[in] pMe Decoder context
1397 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001398
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001399 * @retval QCBOR_ERR_UNSUPPORTED
1400 * @retval QCBOR_ERR_HIT_END
1401 * @retval QCBOR_ERR_INT_OVERFLOW
1402 * @retval QCBOR_ERR_STRING_ALLOCATE
1403 * @retval QCBOR_ERR_STRING_TOO_LONG
1404 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1405 * @retval QCBOR_ERR_BAD_TYPE_7
1406 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1407 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1408 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1409 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1410 * @retval QCBOR_ERR_TOO_MANY_TAGS
1411 *
1412 * This loops getting atomic data items until one is not a tag
1413 * number. Usually this is largely pass-through because most
1414 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001415 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001416static QCBORError
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001417GetNext_TaggedItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001418{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001419 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1420
1421 /* Initialize to CBOR_TAG_INVALID16 */
1422 #if CBOR_TAG_INVALID16 != 0xffff
1423 /* Be sure the memset does the right thing. */
1424 #err CBOR_TAG_INVALID16 tag not defined as expected
1425 #endif
1426 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001427
Laurence Lundblade9b334962020-08-27 10:55:53 -07001428 QCBORError uReturn = QCBOR_SUCCESS;
1429
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001430 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001431 for(;;) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001432 QCBORError uErr = GetNext_FullItem(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001433 if(uErr != QCBOR_SUCCESS) {
1434 uReturn = uErr;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001435 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001436 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001437
Laurence Lundblade9b334962020-08-27 10:55:53 -07001438 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001439 /* Successful exit from loop; maybe got some tags, maybe not */
1440 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001441 break;
1442 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001443
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001444 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1445 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001446 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001447 /* Continue on to get all tags wrapping this item even though
1448 * it is erroring out in the end. This allows decoding to
1449 * continue. This is a resource limit error, not a problem
1450 * with being well-formed CBOR.
1451 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001452 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001453 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001454 /* Slide tags over one in the array to make room at index 0.
1455 * Must use memmove because the move source and destination
1456 * overlap.
1457 */
1458 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001459
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001460 /* Map the tag */
1461 uint16_t uMappedTagNumer;
1462 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1463 /* Continue even on error so as to consume all tags wrapping
1464 * this data item so decoding can go on. If MapTagNumber()
1465 * errors once it will continue to error.
1466 */
1467 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001468 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001469
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001470Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001471 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001472}
1473
1474
1475/*
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001476 * @brief Combine a map entry label and value into one item.
1477 *
1478 * @param[in] pMe Decoder context
1479 * @param[out] pDecodedItem The decoded item that work is done on.
1480 *
1481 * @retval QCBOR_ERR_UNSUPPORTED
1482 * @retval QCBOR_ERR_HIT_END
1483 * @retval QCBOR_ERR_INT_OVERFLOW
1484 * @retval QCBOR_ERR_STRING_ALLOCATE
1485 * @retval QCBOR_ERR_STRING_TOO_LONG
1486 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1487 * @retval QCBOR_ERR_BAD_TYPE_7
1488 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1489 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1490 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1491 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1492 * @retval QCBOR_ERR_TOO_MANY_TAGS
1493 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1494 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1495 *
1496 * If a the current nesting level is a map, then this
1497 * combines pairs of items into one data item with a label
1498 * and value.
1499 *
1500 * This is pass-through if the current nesting leve is
1501 * not a map.
1502 *
1503 * This also implements maps-as-array mode where a map
1504 * is treated like an array to allow caller to do their
1505 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001506 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001507static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001508GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001509{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001510 QCBORError uReturn = GetNext_TaggedItem(me, pDecodedItem);
1511 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512 goto Done;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001513 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001514
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001515 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001516 /* Break can't be a map entry */
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001517 goto Done;
1518 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001519
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001520 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001521 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001522
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001523 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001524 /* Save label in pDecodedItem and get the next which will
1525 * be the real data item.
1526 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001527 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001528 uReturn = GetNext_TaggedItem(me, pDecodedItem);
1529 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001530 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001531 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001532
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301533 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001534
1535 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001536 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001537 pDecodedItem->label.string = LabelItem.val.string;
1538 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1539 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001540 /* It's not a string and we only want strings */
1541 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001542 goto Done;
1543 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1544 pDecodedItem->label.int64 = LabelItem.val.int64;
1545 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1546 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1547 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1548 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1549 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1550 pDecodedItem->label.string = LabelItem.val.string;
1551 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1552 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1553 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001554 /* label is not an int or a string. It is an arrray
1555 * or a float or such and this implementation doesn't handle that.
1556 * Also, tags on labels are ignored.
1557 */
1558 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001559 goto Done;
1560 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001561 }
1562 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001563 /* Decoding of maps as arrays to let the caller decide what to do
1564 * about labels, particularly lables that are not integers or
1565 * strings.
1566 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001567 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001568 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001569 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001570 goto Done;
1571 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001572 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001573 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1574 * Cast is needed because of integer promotion.
1575 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001576 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001577 }
1578 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001579
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001580Done:
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001581 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001582}
1583
1584
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001585#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001586/**
1587 * @brief Peek and see if next data item is a break;
1588 *
1589 * @param[in] pUIB UsefulInputBuf to read from.
1590 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1591 *
1592 * @return Any decoding error.
1593 *
1594 * See if next item is a CBOR break. If it is, it is consumed,
1595 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001596*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001598NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1599{
1600 *pbNextIsBreak = false;
1601 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001602 QCBORItem Peek;
1603 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1604 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1605 if(uReturn != QCBOR_SUCCESS) {
1606 return uReturn;
1607 }
1608 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001609 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001610 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001611 } else {
1612 *pbNextIsBreak = true;
1613 }
1614 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001615
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001616 return QCBOR_SUCCESS;
1617}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001618#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001619
1620
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001621/*
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001622 * @brief Ascend up nesting levels if all items in them have been consumed.
1623 *
1624 * @param[in] pMe The decode context.
1625 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1626 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001627 * An item was just consumed, now figure out if it was the
1628 * end of an array/map map that can be closed out. That
1629 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001630*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001631static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001632{
1633 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001634
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001635 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001636 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1637
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001638 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1639 /* Nesting level is bstr-wrapped CBOR */
1640
1641 /* Ascent for bstr-wrapped CBOR is always by explicit call
1642 * so no further ascending can happen.
1643 */
1644 break;
1645
1646 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1647 /* Level is a definite-length array/map */
1648
1649 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001650 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1651 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001652 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001653 break;
1654 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001655 /* All items in a definite length array were consumed so it
1656 * is time to ascend one level. This happens below.
1657 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001659#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001660 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001661 /* Level is an indefinite-length array/map. */
1662
1663 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001664 bool bIsBreak = false;
1665 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1666 if(uReturn != QCBOR_SUCCESS) {
1667 goto Done;
1668 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001669
1670 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001671 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001672 break;
1673 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001674
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001675 /* It was a break in an indefinite length map / array so
1676 * it is time to ascend one level.
1677 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001678
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001680 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001681
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001682
1683 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001684
Laurence Lundblade93d89472020-10-03 22:30:50 -07001685 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001686 * QCBORDecode_ExitBoundedMode().
1687 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001688 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001689 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001690 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001691 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001692 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001693 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001694
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001695 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001696 break;
1697 }
1698
1699 /* Finally, actually ascend one level. */
1700 DecodeNesting_Ascend(&(pMe->nesting));
1701 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001702
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001703 uReturn = QCBOR_SUCCESS;
1704
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001705#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001706Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001707#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1708
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001709 return uReturn;
1710}
1711
1712
1713/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001714 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001715 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1716 indefinte length maps and arrays by looking at the item count or
1717 finding CBOR breaks. It detects the ends of the top-level sequence
1718 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001719
1720 @retval QCBOR_ERR_UNSUPPORTED X
1721
1722 @retval QCBOR_ERR_HIT_END
1723
1724 @retval QCBOR_ERR_INT_OVERFLOW X
1725
1726 @retval QCBOR_ERR_STRING_ALLOCATE
1727
1728 @retval QCBOR_ERR_STRING_TOO_LONG
1729
1730 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1731
1732 @retval QCBOR_ERR_BAD_TYPE_7 X
1733
1734 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1735
1736 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1737
1738 @retval QCBOR_ERR_TOO_MANY_TAGS
1739
1740 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1741
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001742 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001743
1744 @retval QCBOR_ERR_NO_MORE_ITEMS
1745
1746 @retval QCBOR_ERR_BAD_BREAK
1747
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001748 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001749static QCBORError
1750QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001751{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001752 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001753 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001754
Laurence Lundblade642282a2020-06-23 12:00:33 -07001755 /*
1756 If out of bytes to consume, it is either the end of the top-level
1757 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001758
Laurence Lundblade642282a2020-06-23 12:00:33 -07001759 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1760 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1761 CBOR is exited, the length is set back to the top-level's length
1762 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001763 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001764 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001765 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001766 goto Done;
1767 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001768
Laurence Lundblade642282a2020-06-23 12:00:33 -07001769 /*
1770 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001771 array. The check for a break ending indefinite length array is
1772 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001773 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001774 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001775 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001776 goto Done;
1777 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001778
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001779 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001780 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001781 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1782 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001783 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001784 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301785
Laurence Lundblade642282a2020-06-23 12:00:33 -07001786 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001787 Breaks ending arrays/maps are processed later in the call to
1788 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001789 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301790 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001791 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301792 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301793 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001794
Laurence Lundblade642282a2020-06-23 12:00:33 -07001795 /*
1796 Record the nesting level for this data item before processing any
1797 of decrementing and descending.
1798 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001799 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001800
Laurence Lundblade642282a2020-06-23 12:00:33 -07001801
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001802 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001803 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001804 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001805 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001806
Laurence Lundblade93d89472020-10-03 22:30:50 -07001807 Empty indefinite length maps and arrays are descended into, but
1808 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001809
1810 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001811 encloses them so a decrement needs to be done for them too, but
1812 that is done only when all the items in them have been
1813 processed, not when they are opened with the exception of an
1814 empty map or array.
1815 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001816 QCBORError uDescendErr;
1817 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001818 pDecodedItem->uDataType,
1819 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001820 if(uDescendErr != QCBOR_SUCCESS) {
1821 /* This error is probably a traversal error and it
1822 overrides the non-traversal error. */
1823 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001824 goto Done;
1825 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001826 }
1827
Laurence Lundblade02625d42020-06-25 14:41:41 -07001828 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1829 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1830 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001831 /*
1832 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001833 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001834 - An empty definite length map or array
1835 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001836
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001837 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001838 definite length map/array and break detection for an indefinite
1839 length map/array. If the end of the map/array was reached, then
1840 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001841 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001842 QCBORError uAscendErr;
1843 uAscendErr = NestLevelAscender(me, true);
1844 if(uAscendErr != QCBOR_SUCCESS) {
1845 /* This error is probably a traversal error and it
1846 overrides the non-traversal error. */
1847 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001848 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001849 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301850 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001851
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001852 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001853 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001854 Tell the caller what level is next. This tells them what
1855 maps/arrays were closed out and makes it possible for them to
1856 reconstruct the tree with just the information returned in
1857 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001858 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001859 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001860 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001861 pDecodedItem->uNextNestLevel = 0;
1862 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001863 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001864 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001866Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001867 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001868}
1869
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001870
1871static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001872{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001873 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1874 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1875 }
1876 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001877}
1878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001879
Laurence Lundblade9b334962020-08-27 10:55:53 -07001880
Laurence Lundbladea3336842021-01-03 12:38:36 -08001881/**
1882 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1883 *
1884 * pDecodedItem[in,out] The data item to convert.
1885 *
1886 * @retval QCBOR_ERR_DATE_OVERFLOW
1887 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1888 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1889 *
1890 * The epoch date tag defined in QCBOR allows for floating-point
1891 * dates. It even allows a protocol to flop between date formats when
1892 * ever it wants. Floating-point dates aren't that useful as they are
1893 * only needed for dates beyond the age of the earth.
1894 *
1895 * This converts all the date formats into one format of an unsigned
1896 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001898static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001899{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001900 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001901
1902 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1903
1904 switch (pDecodedItem->uDataType) {
1905
1906 case QCBOR_TYPE_INT64:
1907 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1908 break;
1909
1910 case QCBOR_TYPE_UINT64:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001911 /* This only happens for CBOR type 0 > INT64_MAX so it is
1912 * always an overflow.
1913 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001914 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1915 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001916 break;
1917
1918 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001919 case QCBOR_TYPE_FLOAT:
1920#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001921 {
Laurence Lundbladea3336842021-01-03 12:38:36 -08001922 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001923 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundbladea3336842021-01-03 12:38:36 -08001924 pDecodedItem->val.dfnum :
1925 (double)pDecodedItem->val.fnum;
1926
1927 /* The conversion from float to integer requires overflow
1928 * detection since floats can be much larger than integers.
1929 * This implementation errors out on these large float values
1930 * since they are beyond the age of the earth.
1931 *
1932 * These constants for the overflow check are computed by the
1933 * compiler. They are not computed at run time.
1934 *
1935 * The factor of 0x7ff is added/subtracted to avoid a
1936 * rounding error in the wrong direction when the compiler
1937 * computes these constants. There is rounding because an
1938 * 64-bit integer has 63 bits of precision where a double
1939 * only has 53 bits. Without the 0x7ff factor, the compiler
1940 * may round up and produce a double for the bounds check
1941 * that is larger than can be stored in a 64-bit integer. The
1942 * amoutn of 0x7ff is picked because it has 11 bits set.
1943 *
1944 * Without the 0x7ff there is a ~30 minute range of time
1945 * values 10 billion years in the past and in the future
1946 * where this code could go wrong. Some compilers correctly
1947 * generate a warning or error without the 0x7ff.
1948 */
1949 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1950 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1951
1952 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001953 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 goto Done;
1955 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001956
1957 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001958 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001959 pDecodedItem->val.epochDate.fSecondsFraction =
1960 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001961 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001962#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001963
Laurence Lundbladec7114722020-08-13 05:11:40 -07001964 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001965 goto Done;
1966
Laurence Lundblade9682a532020-06-06 18:33:04 -07001967#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 break;
1969
1970 default:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001971 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001972 goto Done;
1973 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001974
Laurence Lundblade59289e52019-12-30 13:44:37 -08001975 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1976
1977Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001978 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001979}
1980
1981
1982#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1983/*
Laurence Lundbladee176d852021-01-03 17:50:30 -08001984 * @brief Decode decimal fractions and big floats.
1985 *
1986 * @param[in] The decode context.
1987 * @param[in,out] pDecodedItem On input the array data item that
1988 * holds the mantissa and exponent. On
1989 * output the decoded mantissa and
1990 * exponent.
1991 *
1992 * @returns Decoding errors from getting primitive data items or
1993 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
1994 *
1995 * When called pDecodedItem must be the array that is tagged as a big
1996 * float or decimal fraction, the array that has the two members, the
1997 * exponent and mantissa.
1998 *
1999 * This will fetch and decode the exponent and mantissa and put the
2000 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002001 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002002static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
2004{
Laurence Lundbladee176d852021-01-03 17:50:30 -08002005 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002006
Laurence Lundbladee176d852021-01-03 17:50:30 -08002007 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002008 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002009 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002010 goto Done;
2011 }
2012
Laurence Lundbladee176d852021-01-03 17:50:30 -08002013 /* A check for pDecodedItem->val.uCount == 2 would work for
2014 * definite length arrays, but not for indefnite. Instead remember
2015 * the nesting level the two integers must be at, which is one
2016 * deeper than that of the array.
2017 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2019
Laurence Lundbladee176d852021-01-03 17:50:30 -08002020 /* --- Which is it, ecimal fraction or a bigfloat? --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002021 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
2022 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2023
Laurence Lundbladee176d852021-01-03 17:50:30 -08002024 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025 QCBORItem exponentItem;
Laurence Lundbladee176d852021-01-03 17:50:30 -08002026 uReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
2027 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002028 goto Done;
2029 }
2030 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002031 /* Array is empty or a map/array encountered when expecting an int */
2032 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002033 goto Done;
2034 }
2035 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002036 /* Data arriving as an unsigned int < INT64_MAX has been
2037 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2038 * also means that the only data arriving here of type
2039 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2040 * and thus an error that will get handled in the next else.
2041 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2043 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002044 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2045 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002046 goto Done;
2047 }
2048
Laurence Lundbladee176d852021-01-03 17:50:30 -08002049 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002050 QCBORItem mantissaItem;
Laurence Lundbladee176d852021-01-03 17:50:30 -08002051 uReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
2052 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002053 goto Done;
2054 }
2055 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002056 /* Mantissa missing or map/array encountered when expecting number */
2057 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002058 goto Done;
2059 }
2060 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002061 /* Data arriving as an unsigned int < INT64_MAX has been
2062 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2063 * also means that the only data arriving here of type
2064 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2065 * and thus an error that will get handled in an else below.
2066 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002067 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002068 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2069 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002070 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002071 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundbladee176d852021-01-03 17:50:30 -08002072 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002073 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2074 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2075 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002077 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2078 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002079 goto Done;
2080 }
2081
Laurence Lundbladee176d852021-01-03 17:50:30 -08002082 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002083 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002084 /* Extra items in the decimal fraction / big float */
2085 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002086 goto Done;
2087 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002088 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002089
2090Done:
Laurence Lundbladee176d852021-01-03 17:50:30 -08002091 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092}
2093#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2094
2095
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002096static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002097{
2098 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2099 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002100 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002101 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2102 } else {
2103 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002104
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002105 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002106
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002107 return QCBOR_SUCCESS;
2108}
2109
2110
Laurence Lundblade99615302020-11-29 11:19:47 -08002111/*
2112 * Table of CBOR tags whose content is either a text string or a byte
2113 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2114 * of uQCBORtype indicates the content should be a byte string rather
2115 * than a text string
2116 */
2117struct StringTagMapEntry {
2118 uint16_t uTagNumber;
2119 uint8_t uQCBORtype;
2120};
2121
2122#define IS_BYTE_STRING_BIT 0x80
2123#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2124
2125static const struct StringTagMapEntry StringTagMap[] = {
2126 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
2127 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2128 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2129 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2130 {CBOR_TAG_URI, QCBOR_TYPE_URI},
2131 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2132 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2133 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2134 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
2135 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2136 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2137};
2138
2139
2140/*
2141 * Process the CBOR tags that whose content is a byte string or a text
2142 * string and for which the string is just passed on to the caller.
2143 *
2144 * This maps the CBOR tag to the QCBOR type and checks the content
2145 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002146 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002147 * possible.
2148 *
2149 * This returns QCBOR_SUCCESS if the tag was procssed,
2150 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2151 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2152 */
2153static inline
2154QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002155{
Laurence Lundblade99615302020-11-29 11:19:47 -08002156 /* This only works on tags that were not mapped; no need for other yet */
2157 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2158 return QCBOR_ERR_UNSUPPORTED;
2159 }
2160
2161 unsigned uIndex;
2162 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2163 if(StringTagMap[uIndex].uTagNumber == uTag) {
2164 break;
2165 }
2166 }
2167
2168 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2169 if(uQCBORType == QCBOR_TYPE_NONE) {
2170 /* repurpose this error to mean, not handled here */
2171 return QCBOR_ERR_UNSUPPORTED;
2172 }
2173
2174 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2175 if(uQCBORType & IS_BYTE_STRING_BIT) {
2176 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2177 }
2178
2179 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002180 return QCBOR_ERR_BAD_OPT_TAG;
2181 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002182
Laurence Lundblade99615302020-11-29 11:19:47 -08002183 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002184 return QCBOR_SUCCESS;
2185}
2186
2187
Laurence Lundblade59289e52019-12-30 13:44:37 -08002188/*
Laurence Lundblade99615302020-11-29 11:19:47 -08002189 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2190 * but the whole tag was not decoded. Here, the whole tags (tag number
2191 * and tag content) that are supported by QCBOR are decoded. This is a
2192 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002193 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002194static QCBORError
2195QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002196{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002197 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002198
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002199 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2200 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002201 goto Done;
2202 }
2203
Laurence Lundblade99615302020-11-29 11:19:47 -08002204 /* When there are no tag numbers for the item, this exits first
2205 * thing and effectively does nothing.
2206 *
2207 * This loops over all the tag numbers accumulated for this item
2208 * trying to decode and interpret them. This stops at the end of
2209 * the list or at the first tag number that can't be interpreted by
2210 * this code. This is effectively a recursive processing of the
2211 * tags number list that handles nested tags.
2212 */
2213 while(1) {
2214 /* Don't bother to unmap tags via QCBORITem.uTags since this
2215 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2216 */
2217 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002218
Laurence Lundblade99615302020-11-29 11:19:47 -08002219 if(uTagToProcess == CBOR_TAG_INVALID16) {
2220 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002221 break;
2222
Laurence Lundblade99615302020-11-29 11:19:47 -08002223 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002224 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002225
Laurence Lundblade93d89472020-10-03 22:30:50 -07002226#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002227 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2228 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002229 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002230#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002231
Laurence Lundblade99615302020-11-29 11:19:47 -08002232 } else if(uTagToProcess == CBOR_TAG_MIME ||
2233 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002234 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002235
Laurence Lundblade99615302020-11-29 11:19:47 -08002236 } else {
2237 /* See if it is a pass-through byte/text string tag; process if so */
2238 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002239
Laurence Lundblade99615302020-11-29 11:19:47 -08002240 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2241 /* It wasn't a pass-through byte/text string tag so it is
2242 * an unknown tag. This is the exit from the loop on the
2243 * first unknown tag. It is a successful exit.
2244 */
2245 uReturn = QCBOR_SUCCESS;
2246 break;
2247 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002248 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002249
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002250 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002251 /* Error exit from the loop */
2252 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002253 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002254
2255 /* A tag was successfully processed, shift it out of the list of
2256 * tags returned. This is the loop increment.
2257 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002258 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002259 }
2260
2261Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002262 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002263}
2264
2265
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002266/*
2267 Public function, see header qcbor/qcbor_decode.h file
2268 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002269QCBORError
2270QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2271{
2272 QCBORError uErr;
2273 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2274 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002275 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2276 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2277 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002278 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002279}
2280
2281
2282/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002283 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002284 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002285QCBORError
2286QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2287{
2288 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2289 const UsefulInputBuf Save = pMe->InBuf;
2290
2291 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2292
2293 pMe->nesting = SaveNesting;
2294 pMe->InBuf = Save;
2295
2296 return uErr;
2297}
2298
2299
2300/*
2301 Public function, see header qcbor/qcbor_decode.h file
2302 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002303void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2304{
2305 if(pMe->uLastError != QCBOR_SUCCESS) {
2306 return;
2307 }
2308
2309 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2310}
2311
2312
2313/*
2314 Public function, see header qcbor/qcbor_decode.h file
2315 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002316QCBORError
2317QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2318 QCBORItem *pDecodedItem,
2319 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002320{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002321 QCBORError nReturn;
2322
2323 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2324 if(nReturn != QCBOR_SUCCESS) {
2325 return nReturn;
2326 }
2327
2328 if(pTags != NULL) {
2329 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002330 // Reverse the order because pTags is reverse of
2331 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002332 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2333 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002334 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002335 }
2336 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2337 return QCBOR_ERR_TOO_MANY_TAGS;
2338 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002339 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002340 pTags->uNumUsed++;
2341 }
2342 }
2343
2344 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002345}
2346
2347
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302348
2349/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002350 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002351 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002352bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002353 const QCBORItem *pItem,
2354 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002355{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002356 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2357 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002358 break;
2359 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002360 if(UnMapTagNumber(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002361 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002362 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002363 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002364
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002365 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002366}
2367
2368
2369/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002370 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002371 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002372QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002373{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002374 QCBORError uReturn = me->uLastError;
2375
2376 if(uReturn != QCBOR_SUCCESS) {
2377 goto Done;
2378 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002379
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002380 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002381 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002382 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002383 goto Done;
2384 }
2385
2386 // Error out if not all the bytes are consumed
2387 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002388 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002389 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002390
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002391Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002392#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302393 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002394 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002395 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002396#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002397
Laurence Lundblade085d7952020-07-24 10:26:30 -07002398 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002399}
2400
2401
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002402/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002403 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002404*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002405// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002406uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2407 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002408 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002409{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002410 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2411 return CBOR_TAG_INVALID64;
2412 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002413 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2414 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002415 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002416 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002417 }
2418}
2419
Laurence Lundblade9b334962020-08-27 10:55:53 -07002420/*
2421 Public function, see header qcbor/qcbor_decode.h file
2422*/
2423uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2424 uint32_t uIndex)
2425{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002426 if(pMe->uLastError != QCBOR_SUCCESS) {
2427 return CBOR_TAG_INVALID64;
2428 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002429 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2430 return CBOR_TAG_INVALID64;
2431 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002432 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002433 }
2434}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002435
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002436/*
2437
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002438Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002439
Laurence Lundbladeee851742020-01-08 08:37:05 -08002440 - Hit end of input before it was expected while decoding type and
2441 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002442
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002443 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002444
Laurence Lundbladeee851742020-01-08 08:37:05 -08002445 - Hit end of input while decoding a text or byte string
2446 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002447
Laurence Lundbladeee851742020-01-08 08:37:05 -08002448 - Encountered conflicting tags -- e.g., an item is tagged both a date
2449 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002450
Laurence Lundbladeee851742020-01-08 08:37:05 -08002451 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002452 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002453
Laurence Lundbladeee851742020-01-08 08:37:05 -08002454 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002455 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002456
Laurence Lundbladeee851742020-01-08 08:37:05 -08002457 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2458 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002459
Laurence Lundbladeee851742020-01-08 08:37:05 -08002460 - The type of a map label is not a string or int
2461 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002462
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002463 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002464
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002465 */
2466
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002467
2468
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002469#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002470
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002471/* ===========================================================================
2472 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002473
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002474 This implements a simple sting allocator for indefinite length
2475 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2476 implements the function type QCBORStringAllocate and allows easy
2477 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002478
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002479 This particular allocator is built-in for convenience. The caller
2480 can implement their own. All of this following code will get
2481 dead-stripped if QCBORDecode_SetMemPool() is not called.
2482
2483 This is a very primitive memory allocator. It does not track
2484 individual allocations, only a high-water mark. A free or
2485 reallocation must be of the last chunk allocated.
2486
2487 The size of the pool and offset to free memory are packed into the
2488 first 8 bytes of the memory pool so we don't have to keep them in
2489 the decode context. Since the address of the pool may not be
2490 aligned, they have to be packed and unpacked as if they were
2491 serialized data of the wire or such.
2492
2493 The sizes packed in are uint32_t to be the same on all CPU types
2494 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002495 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002496
2497
Laurence Lundbladeee851742020-01-08 08:37:05 -08002498static inline int
2499MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002500{
2501 // Use of UsefulInputBuf is overkill, but it is convenient.
2502 UsefulInputBuf UIB;
2503
Laurence Lundbladeee851742020-01-08 08:37:05 -08002504 // Just assume the size here. It was checked during SetUp so
2505 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002506 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002507 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2508 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2509 return UsefulInputBuf_GetError(&UIB);
2510}
2511
2512
Laurence Lundbladeee851742020-01-08 08:37:05 -08002513static inline int
2514MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002515{
2516 // Use of UsefulOutBuf is overkill, but convenient. The
2517 // length check performed here is useful.
2518 UsefulOutBuf UOB;
2519
2520 UsefulOutBuf_Init(&UOB, Pool);
2521 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2522 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2523 return UsefulOutBuf_GetError(&UOB);
2524}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002525
2526
2527/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002528 Internal function for an allocation, reallocation free and destuct.
2529
2530 Having only one function rather than one each per mode saves space in
2531 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002532
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002533 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2534 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002535static UsefulBuf
2536MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002537{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002538 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002539
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002540 uint32_t uPoolSize;
2541 uint32_t uFreeOffset;
2542
2543 if(uNewSize > UINT32_MAX) {
2544 // This allocator is only good up to 4GB. This check should
2545 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2546 goto Done;
2547 }
2548 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2549
2550 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2551 goto Done;
2552 }
2553
2554 if(uNewSize) {
2555 if(pMem) {
2556 // REALLOCATION MODE
2557 // Calculate pointer to the end of the memory pool. It is
2558 // assumed that pPool + uPoolSize won't wrap around by
2559 // assuming the caller won't pass a pool buffer in that is
2560 // not in legitimate memory space.
2561 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2562
2563 // Check that the pointer for reallocation is in the range of the
2564 // pool. This also makes sure that pointer math further down
2565 // doesn't wrap under or over.
2566 if(pMem >= pPool && pMem < pPoolEnd) {
2567 // Offset to start of chunk for reallocation. This won't
2568 // wrap under because of check that pMem >= pPool. Cast
2569 // is safe because the pool is always less than UINT32_MAX
2570 // because of check in QCBORDecode_SetMemPool().
2571 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2572
2573 // Check to see if the allocation will fit. uPoolSize -
2574 // uMemOffset will not wrap under because of check that
2575 // pMem is in the range of the uPoolSize by check above.
2576 if(uNewSize <= uPoolSize - uMemOffset) {
2577 ReturnValue.ptr = pMem;
2578 ReturnValue.len = uNewSize;
2579
2580 // Addition won't wrap around over because uNewSize was
2581 // checked to be sure it is less than the pool size.
2582 uFreeOffset = uMemOffset + uNewSize32;
2583 }
2584 }
2585 } else {
2586 // ALLOCATION MODE
2587 // uPoolSize - uFreeOffset will not underflow because this
2588 // pool implementation makes sure uFreeOffset is always
2589 // smaller than uPoolSize through this check here and
2590 // reallocation case.
2591 if(uNewSize <= uPoolSize - uFreeOffset) {
2592 ReturnValue.len = uNewSize;
2593 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002594 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002595 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002596 }
2597 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002598 if(pMem) {
2599 // FREE MODE
2600 // Cast is safe because of limit on pool size in
2601 // QCBORDecode_SetMemPool()
2602 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2603 } else {
2604 // DESTRUCT MODE
2605 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002606 }
2607 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002608
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002609 UsefulBuf Pool = {pPool, uPoolSize};
2610 MemPool_Pack(Pool, uFreeOffset);
2611
2612Done:
2613 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002614}
2615
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002616
Laurence Lundbladef6531662018-12-04 10:42:22 +09002617/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002618 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002619 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002620QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2621 UsefulBuf Pool,
2622 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002623{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002624 // The pool size and free mem offset are packed into the beginning
2625 // of the pool memory. This compile time check make sure the
2626 // constant in the header is correct. This check should optimize
2627 // down to nothing.
2628 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002629 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002630 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002631
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002632 // The pool size and free offset packed in to the beginning of pool
2633 // memory are only 32-bits. This check will optimize out on 32-bit
2634 // machines.
2635 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002636 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002637 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002638
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002639 // This checks that the pool buffer given is big enough.
2640 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002641 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002642 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002643
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002644 pMe->StringAllocator.pfAllocator = MemPool_Function;
2645 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2646 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002647
Laurence Lundblade30816f22018-11-10 13:40:22 +07002648 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002649}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002650#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002651
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002652
2653
Laurence Lundblade9b334962020-08-27 10:55:53 -07002654static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2655{
2656 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2657}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002658
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002659
2660/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002661 Consume an entire map or array (and do next to
2662 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002663 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002664static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002665ConsumeItem(QCBORDecodeContext *pMe,
2666 const QCBORItem *pItemToConsume,
2667 uint_fast8_t *puNextNestLevel)
2668{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002669 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002670 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002671
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002672 // If it is a map or array, this will tell if it is empty.
2673 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2674
2675 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2676 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002677
Laurence Lundblade1341c592020-04-11 14:19:05 -07002678 /* This works for definite and indefinite length
2679 * maps and arrays by using the nesting level
2680 */
2681 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002682 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002683 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002684 goto Done;
2685 }
2686 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002688 *puNextNestLevel = Item.uNextNestLevel;
2689
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002690 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002691
Laurence Lundblade1341c592020-04-11 14:19:05 -07002692 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002693 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002694 /* Just pass the nesting level through */
2695 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2696
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002697 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002698 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002699
2700Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002701 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002702}
2703
2704
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705/* Return true if the labels in Item1 and Item2 are the same.
2706 Works only for integer and string labels. Returns false
2707 for any other type. */
2708static inline bool
2709MatchLabel(QCBORItem Item1, QCBORItem Item2)
2710{
2711 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2712 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2713 return true;
2714 }
2715 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002716 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717 return true;
2718 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002719 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002720 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2721 return true;
2722 }
2723 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2724 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2725 return true;
2726 }
2727 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002728
Laurence Lundblade1341c592020-04-11 14:19:05 -07002729 /* Other label types are never matched */
2730 return false;
2731}
2732
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002733
2734/*
2735 Returns true if Item1 and Item2 are the same type
2736 or if either are of QCBOR_TYPE_ANY.
2737 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002738static inline bool
2739MatchType(QCBORItem Item1, QCBORItem Item2)
2740{
2741 if(Item1.uDataType == Item2.uDataType) {
2742 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002743 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002744 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002745 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002746 return true;
2747 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002748 return false;
2749}
2750
2751
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002752/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002753 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002754
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002755 @param[in] pMe The decode context to search.
2756 @param[in,out] pItemArray The items to search for and the items found.
2757 @param[out] puOffset Byte offset of last item matched.
2758 @param[in] pCBContext Context for the not-found item call back.
2759 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002760
2761 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2762
Laurence Lundblade93d89472020-10-03 22:30:50 -07002763 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2764 were found for one of the labels being
2765 search for. This duplicate detection is
2766 only performed for items in pItemArray,
2767 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002768
Laurence Lundblade93d89472020-10-03 22:30:50 -07002769 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2770 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002771
2772 @retval Also errors returned by QCBORDecode_GetNext().
2773
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002774 On input pItemArray contains a list of labels and data types
2775 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002776
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002777 On output the fully retrieved items are filled in with
2778 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002779
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002780 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002781
2782 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002783 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002784static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002785MapSearch(QCBORDecodeContext *pMe,
2786 QCBORItem *pItemArray,
2787 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002788 void *pCBContext,
2789 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002790{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002791 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002792 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002793
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002794 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002795 uReturn = pMe->uLastError;
2796 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002797 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002798
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002799 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002800 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2801 /* QCBOR_TYPE_NONE as first item indicates just looking
2802 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002803 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2804 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002805 }
2806
Laurence Lundblade085d7952020-07-24 10:26:30 -07002807 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2808 // It is an empty bounded array or map
2809 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2810 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002811 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002812 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002813 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002814 // Nothing is ever found in an empty array or map. All items
2815 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002816 uReturn = QCBOR_SUCCESS;
2817 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002818 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002819 }
2820
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002821 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002822 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2823
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002824 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002825 UsefulInputBuf_Seek(&(pMe->InBuf),
2826 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002827
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002828 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002829 Loop over all the items in the map or array. Each item
2830 could be a map or array, but label matching is only at
2831 the main level. This handles definite and indefinite
2832 length maps and arrays. The only reason this is ever
2833 called on arrays is to find their end position.
2834
2835 This will always run over all items in order to do
2836 duplicate detection.
2837
2838 This will exit with failure if it encounters an
2839 unrecoverable error, but continue on for recoverable
2840 errors.
2841
2842 If a recoverable error occurs on a matched item, then
2843 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002844 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002845 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002846 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002847 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002848 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002849 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002850
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002851 /* Get the item */
2852 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002853 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2854 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002855 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002856 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002857 goto Done;
2858 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002859 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002860 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002861 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002862 goto Done;
2863 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002864
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002865 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002866 bool bMatched = false;
2867 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2868 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002869 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002870 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2871 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002872 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002873 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002874 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002875 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002876 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002877 goto Done;
2878 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002879
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002880 if(uResult != QCBOR_SUCCESS) {
2881 uReturn = uResult;
2882 goto Done;
2883 }
2884
Laurence Lundblade1341c592020-04-11 14:19:05 -07002885 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002886 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002887 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002888 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002889 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002890 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002891 bMatched = true;
2892 }
2893 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002894
2895
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002896 if(!bMatched && pfCallback != NULL) {
2897 /*
2898 Call the callback on unmatched labels.
2899 (It is tempting to do duplicate detection here, but that would
2900 require dynamic memory allocation because the number of labels
2901 that might be encountered is unbounded.)
2902 */
2903 uReturn = (*pfCallback)(pCBContext, &Item);
2904 if(uReturn != QCBOR_SUCCESS) {
2905 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002906 }
2907 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002908
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002909 /*
2910 Consume the item whether matched or not. This
2911 does the work of traversing maps and array and
2912 everything in them. In this loop only the
2913 items at the current nesting level are examined
2914 to match the labels.
2915 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002916 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002917 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002918 goto Done;
2919 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002920
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002921 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002922
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002923 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002924
2925 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002926
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002927 // Check here makes sure that this won't accidentally be
2928 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002929 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002930 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2931 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002932 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2933 goto Done;
2934 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002935 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2936 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002937
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002938 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002939 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2940
2941 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002942 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002943 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002944 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002945 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2946 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002947 }
2948 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002949
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002950 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002951}
2952
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002953
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002954/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002955 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002956*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002957void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2958 int64_t nLabel,
2959 uint8_t uQcborType,
2960 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002961{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002962 if(pMe->uLastError != QCBOR_SUCCESS) {
2963 return;
2964 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002965
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002966 QCBORItem OneItemSeach[2];
2967 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2968 OneItemSeach[0].label.int64 = nLabel;
2969 OneItemSeach[0].uDataType = uQcborType;
2970 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002971
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002972 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002973
2974 *pItem = OneItemSeach[0];
2975
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002976 if(uReturn != QCBOR_SUCCESS) {
2977 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002978 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002979 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002980 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002981 }
2982
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002983 Done:
2984 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002985}
2986
2987
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002988/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002989 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002990*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002991void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2992 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002993 uint8_t uQcborType,
2994 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002995{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002996 if(pMe->uLastError != QCBOR_SUCCESS) {
2997 return;
2998 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002999
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003000 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003001 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3002 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3003 OneItemSeach[0].uDataType = uQcborType;
3004 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003005
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003006 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3007 if(uReturn != QCBOR_SUCCESS) {
3008 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003009 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003010 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003011 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003012 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003013 }
3014
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003015 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003016
3017Done:
3018 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003019}
3020
3021
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003022
Laurence Lundblade93d89472020-10-03 22:30:50 -07003023static QCBORError
3024CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003025{
3026 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3027 if(uDataType == puTypeList[i]) {
3028 return QCBOR_SUCCESS;
3029 }
3030 }
3031 return QCBOR_ERR_UNEXPECTED_TYPE;
3032}
3033
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003034
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003035/**
3036 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003037 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003038
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003039 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3040 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003041
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003042 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3043 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003044 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003045static QCBORError
3046CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003047{
3048 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3049 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3050 /* There are tags that QCBOR couldn't process on this item and
3051 the caller has told us there should not be. */
3052 return QCBOR_ERR_UNEXPECTED_TYPE;
3053 }
3054
3055 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3056 const int nItemType = pItem->uDataType;
3057
3058 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3059 // Must match the tag and only the tag
3060 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3061 }
3062
3063 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3064 if(uReturn == QCBOR_SUCCESS) {
3065 return QCBOR_SUCCESS;
3066 }
3067
3068 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3069 /* Must match the content type and only the content type.
3070 There was no match just above so it is a fail. */
3071 return QCBOR_ERR_UNEXPECTED_TYPE;
3072 }
3073
3074 /* If here it can match either the tag or the content
3075 and it hasn't matched the content, so the end
3076 result is whether it matches the tag. This is
3077 also the case that the CBOR standard discourages. */
3078
3079 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3080}
3081
Laurence Lundblade9b334962020-08-27 10:55:53 -07003082
Laurence Lundblade9b334962020-08-27 10:55:53 -07003083
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003084// This could be semi-private if need be
3085static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003086void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3087 int64_t nLabel,
3088 TagSpecification TagSpec,
3089 QCBORItem *pItem)
3090{
3091 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3092 if(pMe->uLastError != QCBOR_SUCCESS) {
3093 return;
3094 }
3095
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003096 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003097}
3098
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003099
3100// This could be semi-private if need be
3101static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003102void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3103 const char *szLabel,
3104 TagSpecification TagSpec,
3105 QCBORItem *pItem)
3106{
3107 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3108 if(pMe->uLastError != QCBOR_SUCCESS) {
3109 return;
3110 }
3111
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003112 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003113}
3114
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003115// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003116void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3117 int64_t nLabel,
3118 TagSpecification TagSpec,
3119 UsefulBufC *pString)
3120{
3121 QCBORItem Item;
3122 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3123 if(pMe->uLastError == QCBOR_SUCCESS) {
3124 *pString = Item.val.string;
3125 }
3126}
3127
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003128// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003129void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3130 const char * szLabel,
3131 TagSpecification TagSpec,
3132 UsefulBufC *pString)
3133{
3134 QCBORItem Item;
3135 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3136 if(pMe->uLastError == QCBOR_SUCCESS) {
3137 *pString = Item.val.string;
3138 }
3139}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003140
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003141/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003142 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003143*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003144void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003145{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003146 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3147 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003148}
3149
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003150/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003151 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003152*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003153void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3154 QCBORItem *pItemList,
3155 void *pCallbackCtx,
3156 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003157{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003158 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3159 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003160}
3161
3162
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003163/**
3164 * @brief Search for a map/array by label and enter it
3165 *
3166 * @param[in] pMe The decode context.
3167 * @param[in] pSearch The map/array to search for.
3168 *
3169 * @c pSearch is expected to contain one item of type map or array
3170 * with the label specified. The current bounded map will be searched for
3171 * this and if found will be entered.
3172 *
3173 * If the label is not found, or the item found is not a map or array,
3174 * the error state is set.
3175 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003176static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003177{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003178 // The first item in pSearch is the one that is to be
3179 // entered. It should be the only one filled in. Any other
3180 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003181 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003182 return;
3183 }
3184
3185 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003186 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003187 if(pMe->uLastError != QCBOR_SUCCESS) {
3188 return;
3189 }
3190
Laurence Lundblade9b334962020-08-27 10:55:53 -07003191 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003192 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003193 return;
3194 }
3195
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003196 /*
3197 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3198 * next item for the pre-order traversal cursor to be the map/array
3199 * found by MapSearch(). The next few lines of code force the
3200 * cursor to that.
3201 *
3202 * There is no need to retain the old cursor because
3203 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3204 * beginning of the map/array being entered.
3205 *
3206 * The cursor is forced by: 1) setting the input buffer position to
3207 * the item offset found by MapSearch(), 2) setting the map/array
3208 * counter to the total in the map/array, 3) setting the nesting
3209 * level. Setting the map/array counter to the total is not
3210 * strictly correct, but this is OK because this cursor only needs
3211 * to be used to get one item and MapSearch() has already found it
3212 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003213 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003214 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003215
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003216 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3217
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003218 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003219
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003220 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003221}
3222
3223
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003224/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003225 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003226*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003227void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003228{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003229 QCBORItem OneItemSeach[2];
3230 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3231 OneItemSeach[0].label.int64 = nLabel;
3232 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3233 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003234
Laurence Lundblade9b334962020-08-27 10:55:53 -07003235 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003236 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003237}
3238
3239
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003240/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003241 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003242*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003243void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003244{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003245 QCBORItem OneItemSeach[2];
3246 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3247 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3248 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3249 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003250
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003251 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003252}
3253
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003254/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003255 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003256*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003257void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003258{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003259 QCBORItem OneItemSeach[2];
3260 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3261 OneItemSeach[0].label.int64 = nLabel;
3262 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3263 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003264
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003265 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003266}
3267
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003268/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003269 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003270*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003271void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3272{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003273 QCBORItem OneItemSeach[2];
3274 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3275 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3276 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3277 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003278
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003279 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003280}
3281
3282
Laurence Lundblade02625d42020-06-25 14:41:41 -07003283// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003284void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003285{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003286 QCBORError uErr;
3287
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003288 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003289 if(pMe->uLastError != QCBOR_SUCCESS) {
3290 // Already in error state; do nothing.
3291 return;
3292 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003293
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003294 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003295 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003296 uErr = QCBORDecode_GetNext(pMe, &Item);
3297 if(uErr != QCBOR_SUCCESS) {
3298 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003299 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003300 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003301 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3302 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003303 }
3304
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003305 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003306
3307
Laurence Lundbladef0499502020-08-01 11:55:57 -07003308 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003309 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003310 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3311 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003312 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003313 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3314 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003315 // Special case to increment nesting level for zero-length maps
3316 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003317 DecodeNesting_Descend(&(pMe->nesting), uType);
3318 }
3319
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003320 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003321
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003322 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3323 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003324
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003325 if(pItem != NULL) {
3326 *pItem = Item;
3327 }
3328
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003329Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003330 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003331}
3332
Laurence Lundblade02625d42020-06-25 14:41:41 -07003333
3334/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003335 This is the common work for exiting a level that is a bounded map,
3336 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003337
3338 One chunk of work is to set up the pre-order traversal so it is at
3339 the item just after the bounded map, array or bstr that is being
3340 exited. This is somewhat complex.
3341
3342 The other work is to level-up the bounded mode to next higest bounded
3343 mode or the top level if there isn't one.
3344 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003345static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003346ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003347{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003348 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003349
Laurence Lundblade02625d42020-06-25 14:41:41 -07003350 /*
3351 First the pre-order-traversal byte offset is positioned to the
3352 item just after the bounded mode item that was just consumed.
3353 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003354 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3355
Laurence Lundblade02625d42020-06-25 14:41:41 -07003356 /*
3357 Next, set the current nesting level to one above the bounded level
3358 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003359
Laurence Lundblade02625d42020-06-25 14:41:41 -07003360 DecodeNesting_CheckBoundedType() is always called before this and
3361 makes sure pCurrentBounded is valid.
3362 */
3363 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3364
3365 /*
3366 This does the complex work of leveling up the pre-order traversal
3367 when the end of a map or array or another bounded level is
3368 reached. It may do nothing, or ascend all the way to the top
3369 level.
3370 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003371 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003372 if(uErr != QCBOR_SUCCESS) {
3373 goto Done;
3374 }
3375
Laurence Lundblade02625d42020-06-25 14:41:41 -07003376 /*
3377 This makes the next highest bounded level the current bounded
3378 level. If there is no next highest level, then no bounded mode is
3379 in effect.
3380 */
3381 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003382
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003383 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003384
3385Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003386 return uErr;
3387}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003388
Laurence Lundblade02625d42020-06-25 14:41:41 -07003389
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003390// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003391void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003392{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003393 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003394 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003395 return;
3396 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003397
Laurence Lundblade02625d42020-06-25 14:41:41 -07003398 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003399
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003400 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003401 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003402 goto Done;
3403 }
3404
Laurence Lundblade02625d42020-06-25 14:41:41 -07003405 /*
3406 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003407 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003408 from previous map search, then do a dummy search.
3409 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003410 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003411 QCBORItem Dummy;
3412 Dummy.uLabelType = QCBOR_TYPE_NONE;
3413 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3414 if(uErr != QCBOR_SUCCESS) {
3415 goto Done;
3416 }
3417 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003418
Laurence Lundblade02625d42020-06-25 14:41:41 -07003419 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003420
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003421Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003422 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003423}
3424
3425
Laurence Lundblade1341c592020-04-11 14:19:05 -07003426
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003427static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003428 const QCBORItem *pItem,
3429 uint8_t uTagRequirement,
3430 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003431{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003432 if(pBstr) {
3433 *pBstr = NULLUsefulBufC;
3434 }
3435
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003436 if(pMe->uLastError != QCBOR_SUCCESS) {
3437 // Already in error state; do nothing.
3438 return pMe->uLastError;
3439 }
3440
3441 QCBORError uError = QCBOR_SUCCESS;
3442
3443 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3444 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3445 goto Done;;
3446 }
3447
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003448 const TagSpecification TagSpec =
3449 {
3450 uTagRequirement,
3451 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3452 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3453 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003454
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003455 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003456 if(uError != QCBOR_SUCCESS) {
3457 goto Done;
3458 }
3459
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003460 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003461 // Reverse the decrement done by GetNext() for the bstr so the
3462 // increment in NestLevelAscender() called by ExitBoundedLevel()
3463 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003464 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003465 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003466
3467 if(pBstr) {
3468 *pBstr = pItem->val.string;
3469 }
3470
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003471 // This saves the current length of the UsefulInputBuf and then
3472 // narrows the UsefulInputBuf to start and length of the wrapped
3473 // CBOR that is being entered.
3474 //
3475 // This makes sure the length is less than
3476 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3477 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3478 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3479 // the casts safe. uEndOfBstr will always be less than
3480 // uPreviousLength because of the way UsefulInputBuf works so there
3481 // is no need to check it. There is also a range check in the
3482 // seek.
3483 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003484 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003485 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003486 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003487 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003488 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003489 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003490 goto Done;
3491 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003492 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003493 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003494 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003495
Laurence Lundblade02625d42020-06-25 14:41:41 -07003496 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003497 (uint32_t)uPreviousLength,
3498 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003499Done:
3500 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003501}
3502
3503
Laurence Lundblade02625d42020-06-25 14:41:41 -07003504/*
3505 Public function, see header qcbor/qcbor_decode.h file
3506 */
3507void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003508 uint8_t uTagRequirement,
3509 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003510{
3511 if(pMe->uLastError != QCBOR_SUCCESS) {
3512 // Already in error state; do nothing.
3513 return;
3514 }
3515
3516 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003517 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003518 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3519 if(pMe->uLastError != QCBOR_SUCCESS) {
3520 return;
3521 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003522
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003523 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003524 &Item,
3525 uTagRequirement,
3526 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003527}
3528
3529
Laurence Lundblade02625d42020-06-25 14:41:41 -07003530/*
3531 Public function, see header qcbor/qcbor_decode.h file
3532 */
3533void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003534 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003535 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003536 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003537{
3538 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003539 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003540
Laurence Lundblade93d89472020-10-03 22:30:50 -07003541 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3542 &Item,
3543 uTagRequirement,
3544 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003545}
3546
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003547
Laurence Lundblade02625d42020-06-25 14:41:41 -07003548/*
3549 Public function, see header qcbor/qcbor_decode.h file
3550 */
3551void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003552 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003553 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003554 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003555{
3556 QCBORItem Item;
3557 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3558
Laurence Lundblade93d89472020-10-03 22:30:50 -07003559 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3560 &Item,
3561 uTagRequirement,
3562 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003563}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003564
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003565
Laurence Lundblade02625d42020-06-25 14:41:41 -07003566/*
3567 Public function, see header qcbor/qcbor_decode.h file
3568 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003569void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003570{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003571 if(pMe->uLastError != QCBOR_SUCCESS) {
3572 // Already in error state; do nothing.
3573 return;
3574 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003575
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003576 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003577 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003578 return;
3579 }
3580
3581 /*
3582 Reset the length of the UsefulInputBuf to what it was before
3583 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003584 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003585 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003586 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003587
3588
Laurence Lundblade02625d42020-06-25 14:41:41 -07003589 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003590 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003591}
3592
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003593
Laurence Lundbladee6430642020-03-14 21:15:44 -07003594
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003595
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003596
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003597
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003598
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003599
Laurence Lundblade93d89472020-10-03 22:30:50 -07003600static QCBORError
3601InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003602{
3603 switch(pItem->uDataType) {
3604 case QCBOR_TYPE_TRUE:
3605 *pBool = true;
3606 return QCBOR_SUCCESS;
3607 break;
3608
3609 case QCBOR_TYPE_FALSE:
3610 *pBool = false;
3611 return QCBOR_SUCCESS;
3612 break;
3613
3614 default:
3615 return QCBOR_ERR_UNEXPECTED_TYPE;
3616 break;
3617 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003618 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003619}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003620
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003621
Laurence Lundblade9b334962020-08-27 10:55:53 -07003622
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003623/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003624 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003625*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003626void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -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
Laurence Lundbladee6430642020-03-14 21:15:44 -07003630 return;
3631 }
3632
Laurence Lundbladec4537442020-04-14 18:53:22 -07003633 QCBORError nError;
3634 QCBORItem Item;
3635
3636 nError = QCBORDecode_GetNext(pMe, &Item);
3637 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003638 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003639 return;
3640 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003641 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003642}
3643
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003645/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003646 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003647*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003648void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003649{
3650 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003651 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003652
Laurence Lundblade9b334962020-08-27 10:55:53 -07003653 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003654}
3655
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003656
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003657/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003658 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003659*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003660void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3661{
3662 QCBORItem Item;
3663 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3664
Laurence Lundblade9b334962020-08-27 10:55:53 -07003665 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003666}
3667
3668
3669
Laurence Lundbladec7114722020-08-13 05:11:40 -07003670
3671static void ProcessEpochDate(QCBORDecodeContext *pMe,
3672 QCBORItem *pItem,
3673 uint8_t uTagRequirement,
3674 int64_t *pnTime)
3675{
3676 if(pMe->uLastError != QCBOR_SUCCESS) {
3677 // Already in error state, do nothing
3678 return;
3679 }
3680
3681 QCBORError uErr;
3682
3683 const TagSpecification TagSpec =
3684 {
3685 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003686 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3687 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003688 };
3689
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003690 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003691 if(uErr != QCBOR_SUCCESS) {
3692 goto Done;
3693 }
3694
3695 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3696 uErr = DecodeDateEpoch(pItem);
3697 if(uErr != QCBOR_SUCCESS) {
3698 goto Done;
3699 }
3700 }
3701
Laurence Lundblade9b334962020-08-27 10:55:53 -07003702 // Save the tags in the last item's tags in the decode context
3703 // for QCBORDecode_GetNthTagOfLast()
3704 CopyTags(pMe, pItem);
3705
Laurence Lundbladec7114722020-08-13 05:11:40 -07003706 *pnTime = pItem->val.epochDate.nSeconds;
3707
3708Done:
3709 pMe->uLastError = (uint8_t)uErr;
3710}
3711
3712
3713void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003714 uint8_t uTagRequirement,
3715 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003716{
3717 if(pMe->uLastError != QCBOR_SUCCESS) {
3718 // Already in error state, do nothing
3719 return;
3720 }
3721
3722 QCBORItem Item;
3723 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3724
3725 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3726}
3727
3728
3729void
3730QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3731 int64_t nLabel,
3732 uint8_t uTagRequirement,
3733 int64_t *pnTime)
3734{
3735 QCBORItem Item;
3736 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3737 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3738}
3739
3740
3741void
3742QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3743 const char *szLabel,
3744 uint8_t uTagRequirement,
3745 int64_t *pnTime)
3746{
3747 QCBORItem Item;
3748 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3749 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3750}
3751
3752
3753
3754
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003755void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3756 TagSpecification TagSpec,
3757 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003759 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003760 // Already in error state, do nothing
3761 return;
3762 }
3763
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003764 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765 QCBORItem Item;
3766
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003767 uError = QCBORDecode_GetNext(pMe, &Item);
3768 if(uError != QCBOR_SUCCESS) {
3769 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770 return;
3771 }
3772
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003773 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003774
3775 if(pMe->uLastError == QCBOR_SUCCESS) {
3776 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003777 } else {
3778 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003779 }
3780}
3781
Laurence Lundbladec4537442020-04-14 18:53:22 -07003782
3783
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003784
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003785static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003786 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003787 UsefulBufC *pValue,
3788 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003789{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003790 const TagSpecification TagSpec =
3791 {
3792 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003793 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3794 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003795 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003796
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003797 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003798 if(uErr != QCBOR_SUCCESS) {
3799 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003800 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003801
3802 *pValue = pItem->val.string;
3803
3804 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3805 *pbIsNegative = false;
3806 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3807 *pbIsNegative = true;
3808 }
3809
3810 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003811}
3812
3813
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003814/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003815 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003816 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003817void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3818 uint8_t uTagRequirement,
3819 UsefulBufC *pValue,
3820 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003821{
3822 if(pMe->uLastError != QCBOR_SUCCESS) {
3823 // Already in error state, do nothing
3824 return;
3825 }
3826
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003827 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003828 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3829 if(uError != QCBOR_SUCCESS) {
3830 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003831 return;
3832 }
3833
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003834 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003835}
3836
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003837
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003838/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003839 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003840*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003841void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3842 int64_t nLabel,
3843 uint8_t uTagRequirement,
3844 UsefulBufC *pValue,
3845 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003846{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003847 QCBORItem Item;
3848 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003849 if(pMe->uLastError != QCBOR_SUCCESS) {
3850 return;
3851 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003852
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003853 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003854}
3855
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003856
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003857/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003858 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003859*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003860void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3861 const char *szLabel,
3862 uint8_t uTagRequirement,
3863 UsefulBufC *pValue,
3864 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003865{
3866 QCBORItem Item;
3867 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003868 if(pMe->uLastError != QCBOR_SUCCESS) {
3869 return;
3870 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003871
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003872 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003873}
3874
3875
3876
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003877
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003878// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003879QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3880 const QCBORItem *pItem,
3881 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003882 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003883{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003884 const TagSpecification TagSpecText =
3885 {
3886 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003887 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3888 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003889 };
3890 const TagSpecification TagSpecBinary =
3891 {
3892 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003893 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3894 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003895 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003896
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003897 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003898
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003899 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003900 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003901 if(pbIsTag257 != NULL) {
3902 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003903 }
3904 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003905 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003906 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003907 if(pbIsTag257 != NULL) {
3908 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003909 }
3910 uReturn = QCBOR_SUCCESS;
3911
3912 } else {
3913 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003915
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003916 return uReturn;
3917}
3918
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919// Improvement: add methods for wrapped CBOR, a simple alternate
3920// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003921
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003922
3923
3924
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003925#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003926
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003927typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003928
3929
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003930// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003931static QCBORError
3932Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003933{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003934 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003935
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003936 if(uResult != 0) {
3937 /* This loop will run a maximum of 19 times because
3938 * UINT64_MAX < 10 ^^ 19. More than that will cause
3939 * exit with the overflow error
3940 */
3941 for(; nExponent > 0; nExponent--) {
3942 if(uResult > UINT64_MAX / 10) {
3943 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3944 }
3945 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003946 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003947
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003948 for(; nExponent < 0; nExponent++) {
3949 uResult = uResult / 10;
3950 if(uResult == 0) {
3951 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3952 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003953 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003954 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003955 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003956
3957 *puResult = uResult;
3958
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003959 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003960}
3961
3962
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003963// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003964static QCBORError
3965Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003967 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003968
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003969 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003970
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003971 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003972 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003973 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003974 */
3975 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003976 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003977 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003978 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003979 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003980 nExponent--;
3981 }
3982
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003983 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003984 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003985 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3986 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003987 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003988 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003989 }
3990
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003991 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003992
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003993 return QCBOR_SUCCESS;
3994}
3995
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003996
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003997/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003998 Compute value with signed mantissa and signed result. Works with
3999 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004000 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004001static inline QCBORError ExponentiateNN(int64_t nMantissa,
4002 int64_t nExponent,
4003 int64_t *pnResult,
4004 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004005{
4006 uint64_t uResult;
4007
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004008 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004009 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004010 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4011
4012 // Do the exponentiation of the positive mantissa
4013 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4014 if(uReturn) {
4015 return uReturn;
4016 }
4017
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004018
Laurence Lundblade983500d2020-05-14 11:49:34 -07004019 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4020 of INT64_MIN. This assumes two's compliment representation where
4021 INT64_MIN is one increment farther from 0 than INT64_MAX.
4022 Trying to write -INT64_MIN doesn't work to get this because the
4023 compiler tries to work with an int64_t which can't represent
4024 -INT64_MIN.
4025 */
4026 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4027
4028 // Error out if too large
4029 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004030 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4031 }
4032
4033 // Casts are safe because of checks above
4034 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4035
4036 return QCBOR_SUCCESS;
4037}
4038
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004039
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004040/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004041 Compute value with signed mantissa and unsigned result. Works with
4042 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004043 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004044static inline QCBORError ExponentitateNU(int64_t nMantissa,
4045 int64_t nExponent,
4046 uint64_t *puResult,
4047 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004048{
4049 if(nMantissa < 0) {
4050 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4051 }
4052
4053 // Cast to unsigned is OK because of check for negative
4054 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4055 // Exponentiation is straight forward
4056 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4057}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004058
4059
4060/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004061 Compute value with signed mantissa and unsigned result. Works with
4062 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004063 */
4064static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4065 int64_t nExponent,
4066 uint64_t *puResult,
4067 fExponentiator pfExp)
4068{
4069 return (*pfExp)(uMantissa, nExponent, puResult);
4070}
4071
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004072#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4073
4074
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004075
4076
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004077
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004078static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004079{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004080 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004081
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004082 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083 const uint8_t *pByte = BigNum.ptr;
4084 size_t uLen = BigNum.len;
4085 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004086 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004087 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004088 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004089 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004090 }
4091
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004092 *pResult = uResult;
4093 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004094}
4095
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004096
Laurence Lundblade887add82020-05-17 05:50:34 -07004097static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004098{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004099 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004100}
4101
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004102
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004103static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004104{
4105 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004106 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4107 if(uError) {
4108 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004109 }
4110 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4111 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004112 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004113}
4114
4115
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004116static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004117{
4118 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004119 /* The negative integer furthest from zero for a C int64_t is
4120 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4121 negative number in CBOR is computed as -n - 1 where n is the
4122 encoded integer, where n is what is in the variable BigNum. When
4123 converting BigNum to a uint64_t, the maximum value is thus
4124 INT64_MAX, so that when it -n - 1 is applied to it the result will
4125 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004126
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004127 -n - 1 <= INT64_MIN.
4128 -n - 1 <= -INT64_MAX - 1
4129 n <= INT64_MAX.
4130 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004131 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004132 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004133 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004134 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004135
4136 /// Now apply -n - 1. The cast is safe because
4137 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4138 // is the largest positive integer that an int64_t can
4139 // represent. */
4140 *pnResult = -(int64_t)uResult - 1;
4141
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004142 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004143}
4144
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004145
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004146
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004147
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004148
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004150Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004151
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004152\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004153
Laurence Lundblade93d89472020-10-03 22:30:50 -07004154\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4155 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004156
4157\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4158
Laurence Lundblade93d89472020-10-03 22:30:50 -07004159\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4160 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004161*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004162static QCBORError
4163ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004164{
4165 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004166 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004168#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004169 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004170 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4171 http://www.cplusplus.com/reference/cmath/llround/
4172 */
4173 // Not interested in FE_INEXACT
4174 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004175 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4176 *pnValue = llround(pItem->val.dfnum);
4177 } else {
4178 *pnValue = lroundf(pItem->val.fnum);
4179 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004180 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4181 // llround() shouldn't result in divide by zero, but catch
4182 // it here in case it unexpectedly does. Don't try to
4183 // distinguish between the various exceptions because it seems
4184 // they vary by CPU, compiler and OS.
4185 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186 }
4187 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004188 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004189 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004190#else
4191 return QCBOR_ERR_HW_FLOAT_DISABLED;
4192#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004193 break;
4194
4195 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004196 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004197 *pnValue = pItem->val.int64;
4198 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004199 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004200 }
4201 break;
4202
4203 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205 if(pItem->val.uint64 < INT64_MAX) {
4206 *pnValue = pItem->val.int64;
4207 } else {
4208 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4209 }
4210 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004211 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 }
4213 break;
4214
4215 default:
4216 return QCBOR_ERR_UNEXPECTED_TYPE;
4217 }
4218 return QCBOR_SUCCESS;
4219}
4220
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004222void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004223 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004224 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004225 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004226{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004227 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004228 return;
4229 }
4230
Laurence Lundbladee6430642020-03-14 21:15:44 -07004231 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004232 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4233 if(uError) {
4234 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004235 return;
4236 }
4237
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004238 if(pItem) {
4239 *pItem = Item;
4240 }
4241
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004242 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004243}
4244
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004245
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4247 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004248 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004249 int64_t *pnValue,
4250 QCBORItem *pItem)
4251{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004252 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004253 if(pMe->uLastError != QCBOR_SUCCESS) {
4254 return;
4255 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004256
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004257 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004258}
4259
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004260
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4262 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004263 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004264 int64_t *pnValue,
4265 QCBORItem *pItem)
4266{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004267 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004268 if(pMe->uLastError != QCBOR_SUCCESS) {
4269 return;
4270 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004271
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004272 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004273}
4274
4275
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004276/*
4277 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004278
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004279 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004280
Laurence Lundblade93d89472020-10-03 22:30:50 -07004281 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4282 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004283
4284 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4285
Laurence Lundblade93d89472020-10-03 22:30:50 -07004286 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4287 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004289static QCBORError
4290Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004291{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004292 switch(pItem->uDataType) {
4293
4294 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004295 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004296 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004297 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004298 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004299 }
4300 break;
4301
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004302 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004303 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004305 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004306 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004307 }
4308 break;
4309
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4311 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004312 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004313 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314 pItem->val.expAndMantissa.nExponent,
4315 pnValue,
4316 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004317 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004318 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004319 }
4320 break;
4321
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004323 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004324 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004325 pItem->val.expAndMantissa.nExponent,
4326 pnValue,
4327 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004328 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004329 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004330 }
4331 break;
4332
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004333 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004335 int64_t nMantissa;
4336 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004337 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4338 if(uErr) {
4339 return uErr;
4340 }
4341 return ExponentiateNN(nMantissa,
4342 pItem->val.expAndMantissa.nExponent,
4343 pnValue,
4344 Exponentitate10);
4345 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004346 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004347 }
4348 break;
4349
4350 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004351 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004352 int64_t nMantissa;
4353 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004354 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4355 if(uErr) {
4356 return uErr;
4357 }
4358 return ExponentiateNN(nMantissa,
4359 pItem->val.expAndMantissa.nExponent,
4360 pnValue,
4361 Exponentitate10);
4362 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004363 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004364 }
4365 break;
4366
4367 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004368 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004369 int64_t nMantissa;
4370 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004371 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4372 if(uErr) {
4373 return uErr;
4374 }
4375 return ExponentiateNN(nMantissa,
4376 pItem->val.expAndMantissa.nExponent,
4377 pnValue,
4378 Exponentitate2);
4379 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004380 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004381 }
4382 break;
4383
4384 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004385 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004386 int64_t nMantissa;
4387 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004388 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4389 if(uErr) {
4390 return uErr;
4391 }
4392 return ExponentiateNN(nMantissa,
4393 pItem->val.expAndMantissa.nExponent,
4394 pnValue,
4395 Exponentitate2);
4396 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004397 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004398 }
4399 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004400#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4401
Laurence Lundbladee6430642020-03-14 21:15:44 -07004402
Laurence Lundbladec4537442020-04-14 18:53:22 -07004403 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004404 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004405}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004406
4407
Laurence Lundbladec4537442020-04-14 18:53:22 -07004408/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004409 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004410 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004411void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004412{
4413 QCBORItem Item;
4414
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004415 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004416
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004417 if(pMe->uLastError == QCBOR_SUCCESS) {
4418 // The above conversion succeeded
4419 return;
4420 }
4421
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004422 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004423 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004424 return;
4425 }
4426
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004427 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004428}
4429
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430
4431/*
4432Public function, see header qcbor/qcbor_decode.h file
4433*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004434void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4435 int64_t nLabel,
4436 uint32_t uConvertTypes,
4437 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004438{
4439 QCBORItem Item;
4440
Laurence Lundblade93d89472020-10-03 22:30:50 -07004441 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4442 nLabel,
4443 uConvertTypes,
4444 pnValue,
4445 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004446
4447 if(pMe->uLastError == QCBOR_SUCCESS) {
4448 // The above conversion succeeded
4449 return;
4450 }
4451
4452 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4453 // The above conversion failed in a way that code below can't correct
4454 return;
4455 }
4456
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004457 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004458}
4459
4460
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004461/*
4462Public function, see header qcbor/qcbor_decode.h file
4463*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004464void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4465 const char *szLabel,
4466 uint32_t uConvertTypes,
4467 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004468{
4469 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004470 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4471 szLabel,
4472 uConvertTypes,
4473 pnValue,
4474 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004475
4476 if(pMe->uLastError == QCBOR_SUCCESS) {
4477 // The above conversion succeeded
4478 return;
4479 }
4480
4481 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4482 // The above conversion failed in a way that code below can't correct
4483 return;
4484 }
4485
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004486 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004487}
4488
4489
Laurence Lundblade93d89472020-10-03 22:30:50 -07004490static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004491{
4492 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004493 case QCBOR_TYPE_DOUBLE:
4494 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004495#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004496 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004497 // Can't use llround here because it will not convert values
4498 // greater than INT64_MAX and less than UINT64_MAX that
4499 // need to be converted so it is more complicated.
4500 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4501 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4502 if(isnan(pItem->val.dfnum)) {
4503 return QCBOR_ERR_FLOAT_EXCEPTION;
4504 } else if(pItem->val.dfnum < 0) {
4505 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4506 } else {
4507 double dRounded = round(pItem->val.dfnum);
4508 // See discussion in DecodeDateEpoch() for
4509 // explanation of - 0x7ff
4510 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4511 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4512 }
4513 *puValue = (uint64_t)dRounded;
4514 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004515 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004516 if(isnan(pItem->val.fnum)) {
4517 return QCBOR_ERR_FLOAT_EXCEPTION;
4518 } else if(pItem->val.fnum < 0) {
4519 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4520 } else {
4521 float fRounded = roundf(pItem->val.fnum);
4522 // See discussion in DecodeDateEpoch() for
4523 // explanation of - 0x7ff
4524 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4525 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4526 }
4527 *puValue = (uint64_t)fRounded;
4528 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004530 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4531 // round() and roundf() shouldn't result in exceptions here, but
4532 // catch them to be robust and thorough. Don't try to
4533 // distinguish between the various exceptions because it seems
4534 // they vary by CPU, compiler and OS.
4535 return QCBOR_ERR_FLOAT_EXCEPTION;
4536 }
4537
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004538 } else {
4539 return QCBOR_ERR_UNEXPECTED_TYPE;
4540 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004541#else
4542 return QCBOR_ERR_HW_FLOAT_DISABLED;
4543#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004544 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004545
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004546 case QCBOR_TYPE_INT64:
4547 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4548 if(pItem->val.int64 >= 0) {
4549 *puValue = (uint64_t)pItem->val.int64;
4550 } else {
4551 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4552 }
4553 } else {
4554 return QCBOR_ERR_UNEXPECTED_TYPE;
4555 }
4556 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004558 case QCBOR_TYPE_UINT64:
4559 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4560 *puValue = pItem->val.uint64;
4561 } else {
4562 return QCBOR_ERR_UNEXPECTED_TYPE;
4563 }
4564 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004565
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004566 default:
4567 return QCBOR_ERR_UNEXPECTED_TYPE;
4568 }
4569
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004570 return QCBOR_SUCCESS;
4571}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004572
4573
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004574void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004575 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004577 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004578{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004579 if(pMe->uLastError != QCBOR_SUCCESS) {
4580 return;
4581 }
4582
Laurence Lundbladec4537442020-04-14 18:53:22 -07004583 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004584
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004585 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4586 if(uError) {
4587 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004588 return;
4589 }
4590
Laurence Lundbladea826c502020-05-10 21:07:00 -07004591 if(pItem) {
4592 *pItem = Item;
4593 }
4594
Laurence Lundblade93d89472020-10-03 22:30:50 -07004595 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004596}
4597
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004598
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004599void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602 uint64_t *puValue,
4603 QCBORItem *pItem)
4604{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004605 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004606 if(pMe->uLastError != QCBOR_SUCCESS) {
4607 return;
4608 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004609
Laurence Lundblade93d89472020-10-03 22:30:50 -07004610 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004611}
4612
4613
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004614void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004616 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617 uint64_t *puValue,
4618 QCBORItem *pItem)
4619{
4620 if(pMe->uLastError != QCBOR_SUCCESS) {
4621 return;
4622 }
4623
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004624 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004625 if(pMe->uLastError != QCBOR_SUCCESS) {
4626 return;
4627 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628
Laurence Lundblade93d89472020-10-03 22:30:50 -07004629 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004630}
4631
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004632
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004633
Laurence Lundblade93d89472020-10-03 22:30:50 -07004634static QCBORError
4635UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004636{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637 switch(pItem->uDataType) {
4638
4639 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004640 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004641 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4642 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 }
4645 break;
4646
4647 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004648 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004649 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4650 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004651 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004652 }
4653 break;
4654
4655#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4656
4657 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004658 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004659 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004660 pItem->val.expAndMantissa.nExponent,
4661 puValue,
4662 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004663 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004664 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004665 }
4666 break;
4667
4668 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4671 pItem->val.expAndMantissa.nExponent,
4672 puValue,
4673 Exponentitate2);
4674 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004675 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004676 }
4677 break;
4678
4679 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004680 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004681 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004682 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004683 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004684 if(uErr != QCBOR_SUCCESS) {
4685 return uErr;
4686 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004687 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688 pItem->val.expAndMantissa.nExponent,
4689 puValue,
4690 Exponentitate10);
4691 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004692 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004693 }
4694 break;
4695
4696 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004697 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004698 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4699 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701 }
4702 break;
4703
4704 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004705 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004706 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004707 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004708 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004709 if(uErr != QCBOR_SUCCESS) {
4710 return uErr;
4711 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004712 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004713 pItem->val.expAndMantissa.nExponent,
4714 puValue,
4715 Exponentitate2);
4716 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004717 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718 }
4719 break;
4720
4721 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004722 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4724 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004725 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726 }
4727 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004728#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729 default:
4730 return QCBOR_ERR_UNEXPECTED_TYPE;
4731 }
4732}
4733
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004734
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004735/*
4736 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004737 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004738void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004739{
4740 QCBORItem Item;
4741
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004742 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004743
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004744 if(pMe->uLastError == QCBOR_SUCCESS) {
4745 // The above conversion succeeded
4746 return;
4747 }
4748
4749 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4750 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004751 return;
4752 }
4753
Laurence Lundblade93d89472020-10-03 22:30:50 -07004754 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004755}
4756
Laurence Lundbladec4537442020-04-14 18:53:22 -07004757
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004759 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004761void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004762 int64_t nLabel,
4763 uint32_t uConvertTypes,
4764 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004765{
4766 QCBORItem Item;
4767
Laurence Lundblade93d89472020-10-03 22:30:50 -07004768 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4769 nLabel,
4770 uConvertTypes,
4771 puValue,
4772 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004773
4774 if(pMe->uLastError == QCBOR_SUCCESS) {
4775 // The above conversion succeeded
4776 return;
4777 }
4778
4779 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4780 // The above conversion failed in a way that code below can't correct
4781 return;
4782 }
4783
Laurence Lundblade93d89472020-10-03 22:30:50 -07004784 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785}
4786
4787
4788/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004789 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004791void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004792 const char *szLabel,
4793 uint32_t uConvertTypes,
4794 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795{
4796 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004797 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4798 szLabel,
4799 uConvertTypes,
4800 puValue,
4801 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802
4803 if(pMe->uLastError == QCBOR_SUCCESS) {
4804 // The above conversion succeeded
4805 return;
4806 }
4807
4808 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4809 // The above conversion failed in a way that code below can't correct
4810 return;
4811 }
4812
Laurence Lundblade93d89472020-10-03 22:30:50 -07004813 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814}
4815
4816
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004817
4818
Laurence Lundblade9b334962020-08-27 10:55:53 -07004819static QCBORError ConvertDouble(const QCBORItem *pItem,
4820 uint32_t uConvertTypes,
4821 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822{
4823 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004824 case QCBOR_TYPE_FLOAT:
4825#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4826 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4827 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004828 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004829 *pdValue = (double)pItem->val.fnum;
4830 } else {
4831 return QCBOR_ERR_UNEXPECTED_TYPE;
4832 }
4833 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004834#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004835 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004836#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004837 break;
4838
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004840 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4841 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 *pdValue = pItem->val.dfnum;
4843 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004845 }
4846 }
4847 break;
4848
4849 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004850#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004851 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004852 // A simple cast seems to do the job with no worry of exceptions.
4853 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 *pdValue = (double)pItem->val.int64;
4855
4856 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004859#else
4860 return QCBOR_ERR_HW_FLOAT_DISABLED;
4861#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862 break;
4863
4864 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004865#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004867 // A simple cast seems to do the job with no worry of exceptions.
4868 // There will be precision loss for some values.
4869 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872 }
4873 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004874#else
4875 return QCBOR_ERR_HW_FLOAT_DISABLED;
4876#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877
4878 default:
4879 return QCBOR_ERR_UNEXPECTED_TYPE;
4880 }
4881
4882 return QCBOR_SUCCESS;
4883}
4884
4885
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004886void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004887 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004888 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004889 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004890{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004891 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004892 return;
4893 }
4894
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004895 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004896
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004897 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004898 if(uError) {
4899 pMe->uLastError = (uint8_t)uError;
4900 return;
4901 }
4902
4903 if(pItem) {
4904 *pItem = Item;
4905 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004906
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004907 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004908}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004909
Laurence Lundbladec4537442020-04-14 18:53:22 -07004910
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004911void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4912 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914 double *pdValue,
4915 QCBORItem *pItem)
4916{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004917 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004918 if(pMe->uLastError != QCBOR_SUCCESS) {
4919 return;
4920 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004922 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004923}
4924
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004925
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4927 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004928 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004929 double *pdValue,
4930 QCBORItem *pItem)
4931{
4932 if(pMe->uLastError != QCBOR_SUCCESS) {
4933 return;
4934 }
4935
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004936 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004937 if(pMe->uLastError != QCBOR_SUCCESS) {
4938 return;
4939 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004940
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004941 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004942}
4943
4944
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004945#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004946static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4947{
4948 double dResult;
4949
4950 dResult = 0.0;
4951 const uint8_t *pByte = BigNum.ptr;
4952 size_t uLen = BigNum.len;
4953 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004954 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004955 while(uLen--) {
4956 dResult = (dResult * 256.0) + (double)*pByte++;
4957 }
4958
4959 return dResult;
4960}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004961#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4962
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004963
Laurence Lundblade93d89472020-10-03 22:30:50 -07004964static QCBORError
4965DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004966{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004967#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004968 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004969 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4970
4971 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004972 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004973
4974#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004975 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004976 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004977 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004978 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4979 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4980 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004981 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004982 }
4983 break;
4984
4985 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004986 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004987 // Underflow gives 0, overflow gives infinity
4988 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4989 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004990 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004991 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004992 }
4993 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004994#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004995
4996 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004997 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4999 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005000 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005001 }
5002 break;
5003
5004 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005005 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005006 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005007 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005008 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005009 }
5010 break;
5011
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005012#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005013 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005014 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005015 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5016 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5017 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005018 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005019 }
5020 break;
5021
5022 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005023 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005024 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5025 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5026 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005027 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005028 }
5029 break;
5030
5031 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005032 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005033 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5034 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5035 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005036 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005037 }
5038 break;
5039
5040 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005041 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005042 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005043 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5044 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005045 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005046 }
5047 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005048#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5049
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005050 default:
5051 return QCBOR_ERR_UNEXPECTED_TYPE;
5052 }
5053
5054 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005055
5056#else
5057 (void)pItem;
5058 (void)uConvertTypes;
5059 (void)pdValue;
5060 return QCBOR_ERR_HW_FLOAT_DISABLED;
5061#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5062
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005063}
5064
5065
5066/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005067 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005068*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005069void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5070 uint32_t uConvertTypes,
5071 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005072{
5073
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005074 QCBORItem Item;
5075
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005076 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005077
5078 if(pMe->uLastError == QCBOR_SUCCESS) {
5079 // The above conversion succeeded
5080 return;
5081 }
5082
5083 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5084 // The above conversion failed in a way that code below can't correct
5085 return;
5086 }
5087
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005088 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005089}
5090
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005091
5092/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005093 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005094*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005095void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5096 int64_t nLabel,
5097 uint32_t uConvertTypes,
5098 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005099{
5100 QCBORItem Item;
5101
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005102 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005103
5104 if(pMe->uLastError == QCBOR_SUCCESS) {
5105 // The above conversion succeeded
5106 return;
5107 }
5108
5109 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5110 // The above conversion failed in a way that code below can't correct
5111 return;
5112 }
5113
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005114 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005115}
5116
5117
5118/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005119 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005120*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005121void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5122 const char *szLabel,
5123 uint32_t uConvertTypes,
5124 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005125{
5126 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005127 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005128
5129 if(pMe->uLastError == QCBOR_SUCCESS) {
5130 // The above conversion succeeded
5131 return;
5132 }
5133
5134 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5135 // The above conversion failed in a way that code below can't correct
5136 return;
5137 }
5138
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005139 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005140}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005141
5142
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005143
5144
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005145#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005146static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5147{
5148 while((uInt & 0xff00000000000000UL) == 0) {
5149 uInt = uInt << 8;
5150 };
5151
5152 UsefulOutBuf UOB;
5153
5154 UsefulOutBuf_Init(&UOB, Buffer);
5155
5156 while(uInt) {
5157 const uint64_t xx = uInt & 0xff00000000000000UL;
5158 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5159 uInt = uInt << 8;
5160 (void)xx;
5161 }
5162
5163 return UsefulOutBuf_OutUBuf(&UOB);
5164}
5165
5166
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005167static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5168 TagSpecification TagSpec,
5169 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005170{
5171 QCBORError uErr;
5172 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005173 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005174 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005175 if(uErr != QCBOR_SUCCESS) {
5176 goto Done;
5177 }
5178
5179 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5180 break; // Successful exit. Moving on to finish decoding.
5181 }
5182
5183 // The item is an array, which means an undecoded
5184 // mantissa and exponent, so decode it. It will then
5185 // have a different type and exit the loop if.
5186 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5187 if(uErr != QCBOR_SUCCESS) {
5188 goto Done;
5189 }
5190
5191 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005192 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005193 }
5194Done:
5195 return uErr;
5196}
5197
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005198
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005199static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005200 TagSpecification TagSpec,
5201 QCBORItem *pItem,
5202 int64_t *pnMantissa,
5203 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005204{
5205 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005206
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005207 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005208 if(uErr != QCBOR_SUCCESS) {
5209 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005210 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005211
Laurence Lundblade9b334962020-08-27 10:55:53 -07005212 switch (pItem->uDataType) {
5213
5214 case QCBOR_TYPE_DECIMAL_FRACTION:
5215 case QCBOR_TYPE_BIGFLOAT:
5216 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5217 *pnExponent = pItem->val.expAndMantissa.nExponent;
5218 break;
5219
5220 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5221 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5222 *pnExponent = pItem->val.expAndMantissa.nExponent;
5223 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5224 break;
5225
5226 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5227 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5228 *pnExponent = pItem->val.expAndMantissa.nExponent;
5229 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5230 break;
5231
5232 default:
5233 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5234 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005235
5236 Done:
5237 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005238}
5239
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005240
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005241static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005242 TagSpecification TagSpec,
5243 QCBORItem *pItem,
5244 UsefulBuf BufferForMantissa,
5245 UsefulBufC *pMantissa,
5246 bool *pbIsNegative,
5247 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005248{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005249 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005250
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005251 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005252 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005253 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005254 }
5255
5256 uint64_t uMantissa;
5257
5258 switch (pItem->uDataType) {
5259
5260 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005261 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005262 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5263 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5264 *pbIsNegative = false;
5265 } else {
5266 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5267 *pbIsNegative = true;
5268 }
5269 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5270 *pnExponent = pItem->val.expAndMantissa.nExponent;
5271 break;
5272
5273 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005274 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005275 *pnExponent = pItem->val.expAndMantissa.nExponent;
5276 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5277 *pbIsNegative = false;
5278 break;
5279
5280 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005281 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005282 *pnExponent = pItem->val.expAndMantissa.nExponent;
5283 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5284 *pbIsNegative = true;
5285 break;
5286
5287 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005288 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005289 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005290
5291Done:
5292 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005293}
5294
5295
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005296/*
5297 Public function, see header qcbor/qcbor_decode.h file
5298*/
5299void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5300 uint8_t uTagRequirement,
5301 int64_t *pnMantissa,
5302 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005303{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005304 if(pMe->uLastError != QCBOR_SUCCESS) {
5305 return;
5306 }
5307
5308 QCBORItem Item;
5309 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5310 if(uError) {
5311 pMe->uLastError = (uint8_t)uError;
5312 return;
5313 }
5314
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005315 const TagSpecification TagSpec =
5316 {
5317 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005318 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5319 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5320 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005321 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005322
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005323 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005324}
5325
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005326
5327/*
5328 Public function, see header qcbor/qcbor_decode.h file
5329*/
5330void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005331 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005332 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005333 int64_t *pnMantissa,
5334 int64_t *pnExponent)
5335{
5336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
5340 QCBORItem Item;
5341 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5342
5343 const TagSpecification TagSpec =
5344 {
5345 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005346 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5347 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5348 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005349 };
5350
5351 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5352}
5353
5354
5355/*
5356 Public function, see header qcbor/qcbor_decode.h file
5357*/
5358void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005359 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005360 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005361 int64_t *pnMantissa,
5362 int64_t *pnExponent)
5363{
5364 if(pMe->uLastError != QCBOR_SUCCESS) {
5365 return;
5366 }
5367
5368 QCBORItem Item;
5369 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5370
5371 const TagSpecification TagSpec =
5372 {
5373 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005374 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5375 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5376 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005377 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005378
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005379 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5380}
5381
5382
5383/*
5384 Public function, see header qcbor/qcbor_decode.h file
5385*/
5386void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5387 uint8_t uTagRequirement,
5388 UsefulBuf MantissaBuffer,
5389 UsefulBufC *pMantissa,
5390 bool *pbMantissaIsNegative,
5391 int64_t *pnExponent)
5392{
5393 if(pMe->uLastError != QCBOR_SUCCESS) {
5394 return;
5395 }
5396
5397 QCBORItem Item;
5398 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5399 if(uError) {
5400 pMe->uLastError = (uint8_t)uError;
5401 return;
5402 }
5403
5404 const TagSpecification TagSpec =
5405 {
5406 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005407 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5408 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5409 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410 };
5411
Laurence Lundblade93d89472020-10-03 22:30:50 -07005412 ProcessMantissaAndExponentBig(pMe,
5413 TagSpec,
5414 &Item,
5415 MantissaBuffer,
5416 pMantissa,
5417 pbMantissaIsNegative,
5418 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005419}
5420
5421
5422/*
5423 Public function, see header qcbor/qcbor_decode.h file
5424*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005425void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005426 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005427 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005428 UsefulBuf BufferForMantissa,
5429 UsefulBufC *pMantissa,
5430 bool *pbIsNegative,
5431 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005432{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005433 if(pMe->uLastError != QCBOR_SUCCESS) {
5434 return;
5435 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005436
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005437 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005438 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005439 if(pMe->uLastError != QCBOR_SUCCESS) {
5440 return;
5441 }
5442
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005443 const TagSpecification TagSpec =
5444 {
5445 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005446 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5447 QCBOR_TYPE_DECIMAL_FRACTION_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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005450
Laurence Lundblade93d89472020-10-03 22:30:50 -07005451 ProcessMantissaAndExponentBig(pMe,
5452 TagSpec,
5453 &Item,
5454 BufferForMantissa,
5455 pMantissa,
5456 pbIsNegative,
5457 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005458}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005459
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005460
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005461/*
5462 Public function, see header qcbor/qcbor_decode.h file
5463*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005464void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005465 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005466 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005467 UsefulBuf BufferForMantissa,
5468 UsefulBufC *pMantissa,
5469 bool *pbIsNegative,
5470 int64_t *pnExponent)
5471{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005472 if(pMe->uLastError != QCBOR_SUCCESS) {
5473 return;
5474 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005475
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005477 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5478 if(pMe->uLastError != QCBOR_SUCCESS) {
5479 return;
5480 }
5481
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482 const TagSpecification TagSpec =
5483 {
5484 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005485 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5486 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5487 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005489
5490 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5491}
5492
5493
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005494/*
5495 Public function, see header qcbor/qcbor_decode.h file
5496*/
5497void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5498 uint8_t uTagRequirement,
5499 int64_t *pnMantissa,
5500 int64_t *pnExponent)
5501{
5502 if(pMe->uLastError != QCBOR_SUCCESS) {
5503 return;
5504 }
5505
5506 QCBORItem Item;
5507 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5508 if(uError) {
5509 pMe->uLastError = (uint8_t)uError;
5510 return;
5511 }
5512 const TagSpecification TagSpec =
5513 {
5514 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005515 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5516 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5517 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005518 };
5519
5520 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5521}
5522
5523
5524/*
5525 Public function, see header qcbor/qcbor_decode.h file
5526*/
5527void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005528 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005529 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005530 int64_t *pnMantissa,
5531 int64_t *pnExponent)
5532{
5533 if(pMe->uLastError != QCBOR_SUCCESS) {
5534 return;
5535 }
5536
5537 QCBORItem Item;
5538 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5539 if(pMe->uLastError != QCBOR_SUCCESS) {
5540 return;
5541 }
5542
5543 const TagSpecification TagSpec =
5544 {
5545 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005546 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5547 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5548 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005549 };
5550
5551 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5552}
5553
5554
5555/*
5556 Public function, see header qcbor/qcbor_decode.h file
5557*/
5558void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005559 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005560 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005561 int64_t *pnMantissa,
5562 int64_t *pnExponent)
5563{
5564 if(pMe->uLastError != QCBOR_SUCCESS) {
5565 return;
5566 }
5567
5568 QCBORItem Item;
5569 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5570 if(pMe->uLastError != QCBOR_SUCCESS) {
5571 return;
5572 }
5573
5574 const TagSpecification TagSpec =
5575 {
5576 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005577 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5578 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5579 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005580 };
5581
5582 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5583}
5584
5585
5586/*
5587 Public function, see header qcbor/qcbor_decode.h file
5588*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005589void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5590 uint8_t uTagRequirement,
5591 UsefulBuf MantissaBuffer,
5592 UsefulBufC *pMantissa,
5593 bool *pbMantissaIsNegative,
5594 int64_t *pnExponent)
5595{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005596 if(pMe->uLastError != QCBOR_SUCCESS) {
5597 return;
5598 }
5599
5600 QCBORItem Item;
5601 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5602 if(uError) {
5603 pMe->uLastError = (uint8_t)uError;
5604 return;
5605 }
5606
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005607 const TagSpecification TagSpec =
5608 {
5609 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005610 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5611 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5612 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005613 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005614
5615 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005616}
5617
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005618
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005619/*
5620 Public function, see header qcbor/qcbor_decode.h file
5621*/
5622void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005623 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005624 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005625 UsefulBuf BufferForMantissa,
5626 UsefulBufC *pMantissa,
5627 bool *pbIsNegative,
5628 int64_t *pnExponent)
5629{
5630 if(pMe->uLastError != QCBOR_SUCCESS) {
5631 return;
5632 }
5633
5634 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005635 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5636 if(pMe->uLastError != QCBOR_SUCCESS) {
5637 return;
5638 }
5639
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005640 const TagSpecification TagSpec =
5641 {
5642 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005643 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5644 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5645 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005646 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005647
Laurence Lundblade93d89472020-10-03 22:30:50 -07005648 ProcessMantissaAndExponentBig(pMe,
5649 TagSpec,
5650 &Item,
5651 BufferForMantissa,
5652 pMantissa,
5653 pbIsNegative,
5654 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005655}
5656
5657
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005658/*
5659 Public function, see header qcbor/qcbor_decode.h file
5660*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005661void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005662 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005663 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005664 UsefulBuf BufferForMantissa,
5665 UsefulBufC *pMantissa,
5666 bool *pbIsNegative,
5667 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005668{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005669 if(pMe->uLastError != QCBOR_SUCCESS) {
5670 return;
5671 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005672
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005673 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005674 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5675 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005676 return;
5677 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005678
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005679 const TagSpecification TagSpec =
5680 {
5681 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005682 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5683 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5684 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005685 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005686
Laurence Lundblade93d89472020-10-03 22:30:50 -07005687 ProcessMantissaAndExponentBig(pMe,
5688 TagSpec,
5689 &Item,
5690 BufferForMantissa,
5691 pMantissa,
5692 pbIsNegative,
5693 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005694}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005695
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005696#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */