blob: e3d38911783ee834e3f16bd2813ce4e41924f971 [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/*
Laurence Lundblade123224b2021-01-03 20:58:06 -0800608 * Decoding items is done in six layers, one calling the next one
609 * down. If a layer has no work to do for a particular item, it
610 * returns quickly.
611 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800612 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
613 * data items, turning them into the local C representation. For the
614 * 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
616 * further decoding and some limited recursion.
Laurence Lundblade123224b2021-01-03 20:58:06 -0800617 *
618 * 2. 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 breaks that terminate
621 * indefinite-length maps and arrays.
622 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800623 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
624 * items, the label and the data, that make up a map entry. It only
625 * does work on maps. It combines the label and data items into one
626 * labeled item.
Laurence Lundblade123224b2021-01-03 20:58:06 -0800627 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800628 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
629 * numbers. It turns the tag numbers into bit flags associated with
630 * the data item. No actual decoding of the contents of the tag is
631 * performed here.
Laurence Lundblade123224b2021-01-03 20:58:06 -0800632 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800633 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
634 * that make up an indefinite-length string into one string item. It
635 * uses the string allocator to create contiguous space for the
636 * item. It processes all breaks that are part of indefinite-length
637 * strings.
Laurence Lundblade123224b2021-01-03 20:58:06 -0800638 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800639 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
640 * CBOR. Each atomic data item has a "major type", an integer
641 * "argument" and optionally some content. For text and byte strings,
642 * the content is the bytes that make up the string. These are the
643 * smallest data items that are considered to be well-formed. The
644 * content may also be other data items in the case of aggregate
645 * types. They are not handled in this layer.
Laurence Lundblade123224b2021-01-03 20:58:06 -0800646 *
647 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
648 * more carefully and correctly.
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800649 */
650
651
Laurence Lundblade1c929722020-12-27 02:44:57 -0800652/**
653 * @brief Decode the CBOR head, the type and argument.
654 *
655 * @param[in] pUInBuf The input buffer to read from.
656 * @param[out] pnMajorType The decoded major type.
657 * @param[out] puArgument The decoded argument.
658 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
659 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -0800660 * @retval QCBOR_ERR_UNSUPPORTED
661 * @retval QCBOR_ERR_HIT_END
Laurence Lundblade1c929722020-12-27 02:44:57 -0800662 *
663 * This decodes the CBOR "head" that every CBOR data item has. See
664 * longer explaination of the head in documentation for
665 * QCBOREncode_EncodeHead().
666 *
667 * This does the network->host byte order conversion. The conversion
668 * here also results in the conversion for floats in addition to that
669 * for lengths, tags and integer values.
670 *
671 * The int type is preferred to uint8_t for some variables as this
672 * avoids integer promotions, can reduce code size and makes static
673 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800675static inline QCBORError
676DecodeHead(UsefulInputBuf *pUInBuf,
677 int *pnMajorType,
678 uint64_t *puArgument,
679 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800681 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800682
Laurence Lundblade1c929722020-12-27 02:44:57 -0800683 /* Get the initial byte that every CBOR data item has and break it
684 * down. */
685 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800686 const int nTmpMajorType = nInitialByte >> 5;
687 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688
Laurence Lundblade1c929722020-12-27 02:44:57 -0800689 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800690 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800692 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800693 /* Need to get 1,2,4 or 8 additional argument bytes. Map
694 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
695 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800696 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundblade1c929722020-12-27 02:44:57 -0800698 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800699 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800700 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800701 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800702 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
703 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800704 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800705 /* The reserved and thus-far unused additional info values */
706 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800707 goto Done;
708 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800709 /* Less than 24, additional info is argument or 31, an
710 * indefinite length. No more bytes to get.
711 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800712 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800716 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 goto Done;
718 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800719
Laurence Lundblade1c929722020-12-27 02:44:57 -0800720 /* All successful if arrived here. */
721 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800723 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800724 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800725
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800727 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728}
729
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800730
Laurence Lundblade1c929722020-12-27 02:44:57 -0800731/**
732 * @brief Decode integer types, major types 0 and 1.
733 *
734 * @param[in] nMajorType The CBOR major type (0 or 1).
735 * @param[in] uArgument The argument from the head.
736 * @param[out] pDecodedItem The filled in decoded item.
737 *
738 * @retval QCBOR_ERR_INT_OVERFLOW
739 *
740 * Must only be called when major type is 0 or 1.
741 *
742 * CBOR doesn't explicitly specify two's compliment for integers but
743 * all CPUs use it these days and the test vectors in the RFC are
744 * so. All integers in the CBOR structure are positive and the major
745 * type indicates positive or negative. CBOR can express positive
746 * integers up to 2^x - 1 where x is the number of bits and negative
747 * integers down to 2^x. Note that negative numbers can be one more
748 * away from zero than positive. Stdint, as far as I can tell, uses
749 * two's compliment to represent negative integers.
750 *
751 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
752 * used carefully here, and in particular why it isn't used in the
753 * public interface. Also see
754 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
755 *
756 * Int is used for values that need less than 16-bits and would be
757 * subject to integer promotion and result in complaining from static
758 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700760static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800761DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700762{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800763 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800764
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700765 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800766 if (uArgument <= INT64_MAX) {
767 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800771 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800774
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700775 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800776 if(uArgument <= INT64_MAX) {
777 /* CBOR's representation of negative numbers lines up with
778 * the two-compliment representation. A negative integer has
779 * one more in range than a positive integer. INT64_MIN is
780 * equal to (-INT64_MAX) - 1.
781 */
782 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800784
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800786 /* C can't represent a negative integer in this range so it
787 * is an error.
788 */
789 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 }
791 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundblade1c929722020-12-27 02:44:57 -0800793 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700794}
795
Laurence Lundblade1c929722020-12-27 02:44:57 -0800796
Laurence Lundblade38299092020-12-28 04:13:50 -0800797/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
799#error QCBOR_TYPE_FALSE macro value wrong
800#endif
801
802#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
803#error QCBOR_TYPE_TRUE macro value wrong
804#endif
805
806#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
807#error QCBOR_TYPE_NULL macro value wrong
808#endif
809
810#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
811#error QCBOR_TYPE_UNDEF macro value wrong
812#endif
813
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700814#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
815#error QCBOR_TYPE_BREAK macro value wrong
816#endif
817
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
819#error QCBOR_TYPE_DOUBLE macro value wrong
820#endif
821
822#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
823#error QCBOR_TYPE_FLOAT macro value wrong
824#endif
825
Laurence Lundblade38299092020-12-28 04:13:50 -0800826
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800827/**
828 * @brief Decode type 7 -- true, false, floating-point, break...
829 *
830 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
831 * @param[in] uArgument The argument from the head.
832 * @param[out] pDecodedItem The filled in decoded item.
833 *
834 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
835 * @retval QCBOR_ERR_BAD_TYPE_7
836 */
Laurence Lundblade9b334962020-08-27 10:55:53 -0700837
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700838static inline QCBORError
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800839DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840{
Laurence Lundblade38299092020-12-28 04:13:50 -0800841 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800842
Laurence Lundblade38299092020-12-28 04:13:50 -0800843 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
844 * checks above make sure uAdditionalInfo values line up with
845 * uDataType values. DecodeHead() never returns an AdditionalInfo
846 * > 0x1f so cast is safe.
847 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800849
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800851 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
852 * are caught before this is called.
853 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundblade38299092020-12-28 04:13:50 -0800855 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700856#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800857 /* Half-precision is returned as a double. The cast to
858 * uint16_t is safe because the encoded value was 16 bits. It
859 * was widened to 64 bits to be passed in here.
860 */
861 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700862 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800864 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800865#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700866 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800867 case SINGLE_PREC_FLOAT: /* 26 */
868 /* Single precision is normally returned as a double since
869 * double is widely supported, there is no loss of precision,
870 * it makes it easy for the caller in most cases and it can
871 * be converted back to single with no loss of precision
872 *
873 * The cast to uint32_t is safe because the encoded value was
874 * 32 bits. It was widened to 64 bits to be passed in here.
875 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800877 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700878#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800879 /* In the normal case, use HW to convert float to
880 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700881 pDecodedItem->val.dfnum = (double)f;
882 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800883#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800884 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885 pDecodedItem->val.fnum = f;
886 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
887
Laurence Lundblade38299092020-12-28 04:13:50 -0800888 /* IEEE754_FloatToDouble() could be used here to return as
889 * a double, but it adds object code and most likely
890 * anyone disabling FLOAT HW use doesn't care about floats
891 * and wants to save object code.
892 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800893#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700895 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700896
Laurence Lundblade38299092020-12-28 04:13:50 -0800897 case DOUBLE_PREC_FLOAT: /* 27 */
898 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700899 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700900 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800901
Laurence Lundblade38299092020-12-28 04:13:50 -0800902 case CBOR_SIMPLEV_FALSE: /* 20 */
903 case CBOR_SIMPLEV_TRUE: /* 21 */
904 case CBOR_SIMPLEV_NULL: /* 22 */
905 case CBOR_SIMPLEV_UNDEF: /* 23 */
906 case CBOR_SIMPLE_BREAK: /* 31 */
907 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundblade38299092020-12-28 04:13:50 -0800909 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
910 if(uArgument <= CBOR_SIMPLE_BREAK) {
911 /* This takes out f8 00 ... f8 1f which should be encoded
912 * as e0 … f7
913 */
914 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700915 goto Done;
916 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800917 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800918
Laurence Lundblade38299092020-12-28 04:13:50 -0800919 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800921 /* DecodeHead() will make uArgument equal to
922 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
923 * safe because the 2, 4 and 8 byte lengths of uNumber are in
924 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800925 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800926 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927 break;
928 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800931 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932}
933
934
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800935/**
936 * @brief Decode text and byte strings
937 *
938 * @param[in] pAllocator The string allocator or NULL.
939 * @param[in] uStrLen The length of the string.
940 * @param[in] pUInBuf The surce from which to read the string's bytes.
941 * @param[out] pDecodedItem The filled in decoded item.
942 *
943 * @retval QCBOR_ERR_HIT_END
944 * @retval QCBOR_ERR_STRING_ALLOCATE
945 * @retval QCBOR_ERR_STRING_TOO_LONG
946 *
947 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
948 * pDecodedItem. If @c pAllocator is not NULL then memory for the
949 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700950 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800951static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800952DecodeBytes(const QCBORInternalAllocator *pAllocator,
953 uint64_t uStrLen,
954 UsefulInputBuf *pUInBuf,
955 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956{
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800957 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800959 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
960 * CPUs. This check makes the casts to size_t below safe.
961 *
962 * The max is 4 bytes less than the largest sizeof() so this can be
963 * tested by putting a SIZE_MAX length in the CBOR test input (no
964 * one will care the limit on strings is 4 bytes shorter).
965 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800967 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800968 goto Done;
969 }
970
971 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530972 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800973 /* Failed to get the bytes for this string item */
974 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530975 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530977
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800978#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800979 /* Note that this is not where allocation to coallsece
980 * indefinite-length strings is done. This is for when the caller
981 * has requested all strings be allocated. Disabling indefinite
982 * length strings also disables this allocate-all option.
983 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800984 if(pAllocator) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800985 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530987 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800988 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530989 goto Done;
990 }
991 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800992 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800993 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530994 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800995#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
996 (void)pAllocator;
997#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
998
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800999 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001000 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301002Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001003 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004}
1005
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001006
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001007/**
1008 * @brief Map the CBOR major types for strings to the QCBOR types.
1009 *
1010 * @param[in] nCBORMajorType The CBOR major type to convert.
1011 * @retturns QCBOR type number.
1012 *
1013 * This only works for the two string types.
1014 */
1015static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001016{
1017 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1018 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1019 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001020
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1022 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1023 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001025 return (uint8_t)(nCBORMajorType + 4);
1026}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027
1028
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001029/**
1030 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1031 *
1032 * @param[in] nCBORMajorType The CBOR major type to convert.
1033 * @retturns QCBOR type number.
1034 *
1035 * This only works for the two aggregate types.
1036 */
1037static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
1038{
1039 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1040 #error QCBOR_TYPE_ARRAY value not lined up with major type
1041 #endif
1042
1043 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1044 #error QCBOR_TYPE_MAP value not lined up with major type
1045 #endif
1046
1047 return (uint8_t)(nCBORMajorType);
1048}
1049
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001051/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001052 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001053 *
1054 * @param[in] pUInBuf Input buffer to read data item from.
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001055 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001056 * @param[in] pAllocator The allocator to use for strings or NULL.
1057 *
1058 * @retval QCBOR_ERR_UNSUPPORTED
1059 * @retval QCBOR_ERR_HIT_END
1060 * @retval QCBOR_ERR_INT_OVERFLOW
1061 * @retval QCBOR_ERR_STRING_ALLOCATE
1062 * @retval QCBOR_ERR_STRING_TOO_LONG
1063 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1064 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001065 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001066 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001067 * This decodes the most primitive / atomic data item. It does
1068 * no combing of data items.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001069 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001070static QCBORError
1071DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1072 QCBORItem *pDecodedItem,
1073 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074{
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001075 QCBORError uReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001077 /* Get the major type and the argument. The argument could be
1078 * length of more bytes or the value depending on the major
1079 * type. nAdditionalInfo is an encoding of the length of the
1080 * uNumber and is needed to decode floats and doubles.
1081 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001082 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001083 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001084 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001086 memset(pDecodedItem, 0, sizeof(QCBORItem));
1087
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001088 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1089 if(uReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001090 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001093 /* At this point the major type and the argument are valid. We've
1094 * got the type and the argument that starts every CBOR data item.
1095 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001096 switch (nMajorType) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001097 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1098 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001099 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001100 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001101 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001102 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001103 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001106 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1107 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1108 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001109 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001110 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001112 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 }
1114 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001115
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001116 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1117 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001118 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001119 /* Indefinite-length string. */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001120#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001121 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001122#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001123 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001124 break;
1125#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001127 /* Definite-length string. */
1128 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1129 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1130 goto Done;
1131 }
1132 /* cast OK because of check above */
Laurence Lundblade1c929722020-12-27 02:44:57 -08001133 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001134 }
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001135 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001136 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001137
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001138 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001139 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001140 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001141 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001142 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001143 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001144 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001146
Laurence Lundbladeee851742020-01-08 08:37:05 -08001147 case CBOR_MAJOR_TYPE_SIMPLE:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001148 /* Major type 7: float, double, true, false, null... */
1149 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001150 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundbladeee851742020-01-08 08:37:05 -08001152 default:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001153 /* Never happens because DecodeHead() should never return > 7 */
1154 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155 break;
1156 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001159 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001160}
1161
1162
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001163/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001164 * @brief Process indefinite length strings (decode layer 5).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 *
1166 * @param[in] pMe Decoder context
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001167 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001168 *
1169 * @retval QCBOR_ERR_UNSUPPORTED
1170 * @retval QCBOR_ERR_HIT_END
1171 * @retval QCBOR_ERR_INT_OVERFLOW
1172 * @retval QCBOR_ERR_STRING_ALLOCATE
1173 * @retval QCBOR_ERR_STRING_TOO_LONG
1174 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1175 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001176 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001177 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1178 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001179 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001180 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001181 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001182 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001183 * If it is, this loops getting the subsequent chunk data items that
1184 * make up the string. The string allocator is used to make a
1185 * contiguous buffer for the chunks. When this completes @c
1186 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 *
1188 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001190static inline QCBORError
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001191QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001192{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 /* Aproximate stack usage
1194 * 64-bit 32-bit
1195 * local vars 32 16
1196 * 2 UsefulBufs 32 16
1197 * QCBORItem 56 52
1198 * TOTAL 120 74
1199 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001200
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001201 /* The string allocator is used here for two purposes: 1)
1202 * coalescing the chunks of an indefinite length string, 2)
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001203 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204 *
1205 * The first use is below in this function. Indefinite length
1206 * strings cannot be processed at all without a string allocator.
1207 *
1208 * The second used is in DecodeBytes() which is called by
1209 * GetNext_Item() below. This second use unneccessary for most use
1210 * and only happens when requested in the call to
1211 * QCBORDecode_SetMemPool(). If the second use not requested then
1212 * NULL is passed for the string allocator to GetNext_Item().
1213 *
1214 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1215 * allocator altogether and thus both of these uses. It reduced the
1216 * decoder object code by about 400 bytes.
1217 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001218 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001219
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001220#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001221 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001222
1223 if(pMe->StringAllocator.pfAllocator) {
1224 pAllocator = &(pMe->StringAllocator);
1225 if(pMe->bStringAllocateAll) {
1226 pAllocatorForGetNext = pAllocator;
1227 }
1228 }
1229#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1230
1231 QCBORError uReturn;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001232 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001233 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001234 goto Done;
1235 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001236
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001237 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001238 const uint8_t uStringType = pDecodedItem->uDataType;
1239 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001240 goto Done;
1241 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001243 /* Is this a string with an indefinite length? */
1244 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1245 goto Done;
1246 }
1247
1248#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1249 /* Can't do indefinite length strings without a string allocator */
1250 if(pAllocator == NULL) {
1251 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1252 goto Done;
1253 }
1254
1255 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001256 UsefulBufC FullString = NULLUsefulBufC;
1257
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001258 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001259 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001260 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001261 /* Pass a NULL string allocator to GetNext_Item() because the
1262 * individual string chunks in an indefinite length should not
1263 * be allocated. They are always copied in the the contiguous
1264 * buffer allocated here.
1265 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001266 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001267 if(uReturn) {
1268 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001271 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001272 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001273 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301275 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001276 break;
1277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001278
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279 /* All chunks must be of the same type, the type of the item
1280 * that introduces the indefinite length string. This also
1281 * catches errors where the chunk is not a string at all and an
1282 * indefinite length string inside an indefinite length string.
1283 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001284 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001285 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1286 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001287 break;
1288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001289
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001290 /* The first time throurgh FullString.ptr is NULL and this is
1291 * equivalent to StringAllocator_Allocate(). Subsequently it is
1292 * not NULL and a reallocation happens.
1293 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001294 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1295 UNCONST_POINTER(FullString.ptr),
1296 FullString.len + StringChunkItem.val.string.len);
1297
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001298 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001300 break;
1301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001302
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001303 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001304 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001305 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001306
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001307 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1308 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001309 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001310 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001311#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1312 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1313#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001314
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001315Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001317}
1318
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001319
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001320/**
1321 * @brief This converts a tag number to a shorter mapped value for storage.
1322 *
1323 * @param[in] pMe The decode context.
1324 * @param[in] uUnMappedTag The tag number to map
1325 * @param[out] puMappedTagNumer The stored tag number.
1326 *
1327 * @return error code.
1328 *
1329 * The main point of mapping tag numbers is make QCBORItem
1330 * smaller. With this mapping storage of 4 tags takes up 8
1331 * bytes. Without, it would take up 32 bytes.
1332 *
1333 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1334 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1335 *
1336 * See also UnMapTagNumber() and @ref QCBORItem.
1337 */
1338static inline QCBORError
1339MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1340{
1341 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001342 unsigned uTagMapIndex;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001343 /* Is there room in the tag map, or is it in it already? */
1344 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1345 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1346 break;
1347 }
1348 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1349 break;
1350 }
1351 }
1352 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1353 return QCBOR_ERR_TOO_MANY_TAGS;
1354 }
1355
1356 /* Covers the cases where tag is new and were it is already in the map */
1357 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1358 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1359
1360 } else {
1361 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1362 }
1363
1364 return QCBOR_SUCCESS;
1365}
1366
1367
1368/**
1369 * @brief This converts a mapped tag number to the actual tag number.
1370 *
1371 * @param[in] pMe The decode context.
1372 * @param[in] uMappedTagNumber The stored tag number.
1373 *
1374 * @return The actual tag number is returned or
1375 * @ref CBOR_TAG_INVALID64 on error.
1376 *
1377 * This is the reverse of MapTagNumber()
1378 */
1379static uint64_t
1380UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1381{
1382 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1383 return uMappedTagNumber;
1384 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001385 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001386 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001387 /* This won't be negative because of code below in
1388 * MapTagNumber()
1389 */
1390 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1391 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001392 }
1393}
1394
Laurence Lundblade9b334962020-08-27 10:55:53 -07001395
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001396/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001397 * @brief Aggregate all tags wrapping a data item (decode layer 4).
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001398 *
1399 * @param[in] pMe Decoder context
1400 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001401
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001402 * @retval QCBOR_ERR_UNSUPPORTED
1403 * @retval QCBOR_ERR_HIT_END
1404 * @retval QCBOR_ERR_INT_OVERFLOW
1405 * @retval QCBOR_ERR_STRING_ALLOCATE
1406 * @retval QCBOR_ERR_STRING_TOO_LONG
1407 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1408 * @retval QCBOR_ERR_BAD_TYPE_7
1409 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1410 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1411 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1412 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1413 * @retval QCBOR_ERR_TOO_MANY_TAGS
1414 *
1415 * This loops getting atomic data items until one is not a tag
1416 * number. Usually this is largely pass-through because most
1417 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001418 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001419static QCBORError
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001420QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001421{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001422 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1423
1424 /* Initialize to CBOR_TAG_INVALID16 */
1425 #if CBOR_TAG_INVALID16 != 0xffff
1426 /* Be sure the memset does the right thing. */
1427 #err CBOR_TAG_INVALID16 tag not defined as expected
1428 #endif
1429 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001430
Laurence Lundblade9b334962020-08-27 10:55:53 -07001431 QCBORError uReturn = QCBOR_SUCCESS;
1432
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001433 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001434 for(;;) {
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001435 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001436 if(uErr != QCBOR_SUCCESS) {
1437 uReturn = uErr;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001438 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001439 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001440
Laurence Lundblade9b334962020-08-27 10:55:53 -07001441 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001442 /* Successful exit from loop; maybe got some tags, maybe not */
1443 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001444 break;
1445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001446
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001447 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1448 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001449 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001450 /* Continue on to get all tags wrapping this item even though
1451 * it is erroring out in the end. This allows decoding to
1452 * continue. This is a resource limit error, not a problem
1453 * with being well-formed CBOR.
1454 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001455 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001456 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001457 /* Slide tags over one in the array to make room at index 0.
1458 * Must use memmove because the move source and destination
1459 * overlap.
1460 */
1461 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001463 /* Map the tag */
1464 uint16_t uMappedTagNumer;
1465 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1466 /* Continue even on error so as to consume all tags wrapping
1467 * this data item so decoding can go on. If MapTagNumber()
1468 * errors once it will continue to error.
1469 */
1470 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001471 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001473Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001474 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001475}
1476
1477
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001478/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001479 * @brief Combine a map entry label and value into one item (decode layer 3).
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001480 *
1481 * @param[in] pMe Decoder context
1482 * @param[out] pDecodedItem The decoded item that work is done on.
1483 *
1484 * @retval QCBOR_ERR_UNSUPPORTED
1485 * @retval QCBOR_ERR_HIT_END
1486 * @retval QCBOR_ERR_INT_OVERFLOW
1487 * @retval QCBOR_ERR_STRING_ALLOCATE
1488 * @retval QCBOR_ERR_STRING_TOO_LONG
1489 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1490 * @retval QCBOR_ERR_BAD_TYPE_7
1491 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1492 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1493 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1494 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1495 * @retval QCBOR_ERR_TOO_MANY_TAGS
1496 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1497 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1498 *
1499 * If a the current nesting level is a map, then this
1500 * combines pairs of items into one data item with a label
1501 * and value.
1502 *
1503 * This is pass-through if the current nesting leve is
1504 * not a map.
1505 *
1506 * This also implements maps-as-array mode where a map
1507 * is treated like an array to allow caller to do their
1508 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001509 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001510static inline QCBORError
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001511QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512{
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001513 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001514 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001515 goto Done;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001516 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001517
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001518 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001519 /* Break can't be a map entry */
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001520 goto Done;
1521 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001522
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001523 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001524 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001525
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001526 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001527 /* Save label in pDecodedItem and get the next which will
1528 * be the real data item.
1529 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001530 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001531 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001532 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001533 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001534 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301536 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001537
1538 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001539 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001540 pDecodedItem->label.string = LabelItem.val.string;
1541 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001542 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001543 /* It's not a string and we only want strings */
1544 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001545 goto Done;
1546 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1547 pDecodedItem->label.int64 = LabelItem.val.int64;
1548 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1549 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1550 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1551 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1552 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1553 pDecodedItem->label.string = LabelItem.val.string;
1554 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1555 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1556 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001557 /* label is not an int or a string. It is an arrray
1558 * or a float or such and this implementation doesn't handle that.
1559 * Also, tags on labels are ignored.
1560 */
1561 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001562 goto Done;
1563 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001564 }
1565 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001566 /* Decoding of maps as arrays to let the caller decide what to do
1567 * about labels, particularly lables that are not integers or
1568 * strings.
1569 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001570 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001571 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001572 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001573 goto Done;
1574 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001575 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001576 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1577 * Cast is needed because of integer promotion.
1578 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001579 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001580 }
1581 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001582
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001583Done:
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001584 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001585}
1586
1587
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001588#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001589/**
1590 * @brief Peek and see if next data item is a break;
1591 *
1592 * @param[in] pUIB UsefulInputBuf to read from.
1593 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1594 *
1595 * @return Any decoding error.
1596 *
1597 * See if next item is a CBOR break. If it is, it is consumed,
1598 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001599*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001600static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001601NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1602{
1603 *pbNextIsBreak = false;
1604 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001605 QCBORItem Peek;
1606 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001607 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001608 if(uReturn != QCBOR_SUCCESS) {
1609 return uReturn;
1610 }
1611 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001612 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001613 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001614 } else {
1615 *pbNextIsBreak = true;
1616 }
1617 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001618
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001619 return QCBOR_SUCCESS;
1620}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001621#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001622
1623
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001624/**
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001625 * @brief Ascend up nesting levels if all items in them have been consumed.
1626 *
1627 * @param[in] pMe The decode context.
1628 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1629 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001630 * An item was just consumed, now figure out if it was the
1631 * end of an array/map map that can be closed out. That
1632 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001633*/
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001634static QCBORError
1635QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001636{
1637 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001638
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001639 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001640 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1641
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001642 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1643 /* Nesting level is bstr-wrapped CBOR */
1644
1645 /* Ascent for bstr-wrapped CBOR is always by explicit call
1646 * so no further ascending can happen.
1647 */
1648 break;
1649
1650 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1651 /* Level is a definite-length array/map */
1652
1653 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001654 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1655 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001656 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001657 break;
1658 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001659 /* All items in a definite length array were consumed so it
1660 * is time to ascend one level. This happens below.
1661 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001662
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001663#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001664 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001665 /* Level is an indefinite-length array/map. */
1666
1667 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001668 bool bIsBreak = false;
1669 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1670 if(uReturn != QCBOR_SUCCESS) {
1671 goto Done;
1672 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001673
1674 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001675 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001676 break;
1677 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001678
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679 /* It was a break in an indefinite length map / array so
1680 * it is time to ascend one level.
1681 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001682
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001683#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001684 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001685
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001686
1687 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001688
Laurence Lundblade93d89472020-10-03 22:30:50 -07001689 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001690 * QCBORDecode_ExitBoundedMode().
1691 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001692 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001693 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001694 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001695 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001696 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001697 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001698
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001699 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001700 break;
1701 }
1702
1703 /* Finally, actually ascend one level. */
1704 DecodeNesting_Ascend(&(pMe->nesting));
1705 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001707 uReturn = QCBOR_SUCCESS;
1708
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001709#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001710Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001711#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1712
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001713 return uReturn;
1714}
1715
1716
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001717/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001718 * @brief Ascending & Descending out of nesting levels (decode layer 2).
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001719 *
1720 * @param[in] pMe Decoder context
1721 * @param[out] pDecodedItem The decoded item that work is done on.
1722 *
1723 * @retval QCBOR_ERR_UNSUPPORTED
1724 * @retval QCBOR_ERR_HIT_END
1725 * @retval QCBOR_ERR_INT_OVERFLOW
1726 * @retval QCBOR_ERR_STRING_ALLOCATE
1727 * @retval QCBOR_ERR_STRING_TOO_LONG
1728 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1729 * @retval QCBOR_ERR_BAD_TYPE_7
1730 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1731 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1732 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1733 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1734 * @retval QCBOR_ERR_TOO_MANY_TAGS
1735 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1736 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1737 * @retval QCBOR_ERR_NO_MORE_ITEMS
1738 * @retval QCBOR_ERR_BAD_BREAK
1739 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1740 *
1741 * This handles the traversal descending into and asecnding out of
1742 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1743 * definite and indefinte-length maps and arrays by looking at the
1744 * item count or finding CBOR breaks. It detects the ends of the
1745 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001746 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001747static QCBORError
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001748QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001749{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001750 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001751 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001752
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001753 /* If out of bytes to consume, it is either the end of the
1754 * top-level sequence of some bstr-wrapped CBOR that was entered.
1755 *
1756 * In the case of bstr-wrapped CBOR, the length of the
1757 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1758 * the bstr-wrapped CBOR is exited, the length is set back to the
1759 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001760 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001761 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001762 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001763 goto Done;
1764 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001765
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001766 /* Check to see if at the end of a bounded definite length map or
1767 * array. The check for a break ending indefinite length array is
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001768 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001769 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001770 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001771 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001772 goto Done;
1773 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001774
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001775 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001776 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001777 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1778 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001779 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001780 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301781
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001782 /* Breaks ending arrays/maps are processed later in the call to
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001783 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001784 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301785 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001786 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301787 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301788 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001789
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001790 /* Record the nesting level for this data item before processing
1791 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001792 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001793 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001794
Laurence Lundblade642282a2020-06-23 12:00:33 -07001795
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001796 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001797 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001798 /* If the new item is a map or array, descend.
1799 *
1800 * Empty indefinite length maps and arrays are descended into,
1801 * but then ascended out of in the next chunk of code.
1802 *
1803 * Maps and arrays do count as items in the map/array that
1804 * encloses them so a decrement needs to be done for them too,
1805 * but that is done only when all the items in them have been
1806 * processed, not when they are opened with the exception of an
1807 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001808 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001809 QCBORError uDescendErr;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001810 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001811 pDecodedItem->uDataType,
1812 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001813 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001814 /* This error is probably a traversal error and it overrides
1815 * the non-traversal error.
1816 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001817 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001818 goto Done;
1819 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001820 }
1821
Laurence Lundblade02625d42020-06-25 14:41:41 -07001822 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1823 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1824 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001825 /* The following cases are handled here:
1826 * - A non-aggregate item like an integer or string
1827 * - An empty definite length map or array
1828 * - An indefinite length map or array that might be empty or might not.
1829 *
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001830 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001831 * for an definite length map/array and break detection for an
1832 * indefinite length map/array. If the end of the map/array was
1833 * reached, then it ascends nesting levels, possibly all the way
1834 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001835 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001836 QCBORError uAscendErr;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001837 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001838 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001839 /* This error is probably a traversal error and it overrides
1840 * the non-traversal error.
1841 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001842 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001843 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001844 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301845 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001846
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001847 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001848 /* Tell the caller what level is next. This tells them what
1849 * maps/arrays were closed out and makes it possible for them to
1850 * reconstruct the tree with just the information returned in a
1851 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001852 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001853 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001854 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001855 pDecodedItem->uNextNestLevel = 0;
1856 } else {
Laurence Lundblade7c12e252021-01-04 15:44:18 -08001857 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001858 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001859
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001860Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001861 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001862}
1863
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001864
Laurence Lundblade00c54bf2021-01-03 23:17:38 -08001865/**
1866 * @brief Shift 0th tag out of the tag list.
1867 *
1868 * pDecodedItem[in,out] The data item to convert.
1869 *
1870 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1871 * shifted into empty slot at the end of the tag list.
1872 */
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001873static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001874{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001875 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1876 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1877 }
1878 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001879}
1880
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001881
Laurence Lundbladea3336842021-01-03 12:38:36 -08001882/**
1883 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1884 *
1885 * pDecodedItem[in,out] The data item to convert.
1886 *
1887 * @retval QCBOR_ERR_DATE_OVERFLOW
1888 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1889 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1890 *
1891 * The epoch date tag defined in QCBOR allows for floating-point
1892 * dates. It even allows a protocol to flop between date formats when
1893 * ever it wants. Floating-point dates aren't that useful as they are
1894 * only needed for dates beyond the age of the earth.
1895 *
1896 * This converts all the date formats into one format of an unsigned
1897 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001898 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001899static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001900{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001901 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001902
1903 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1904
1905 switch (pDecodedItem->uDataType) {
1906
1907 case QCBOR_TYPE_INT64:
1908 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1909 break;
1910
1911 case QCBOR_TYPE_UINT64:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001912 /* This only happens for CBOR type 0 > INT64_MAX so it is
1913 * always an overflow.
1914 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001915 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1916 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001917 break;
1918
1919 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001920 case QCBOR_TYPE_FLOAT:
1921#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922 {
Laurence Lundbladea3336842021-01-03 12:38:36 -08001923 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001924 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundbladea3336842021-01-03 12:38:36 -08001925 pDecodedItem->val.dfnum :
1926 (double)pDecodedItem->val.fnum;
1927
1928 /* The conversion from float to integer requires overflow
1929 * detection since floats can be much larger than integers.
1930 * This implementation errors out on these large float values
1931 * since they are beyond the age of the earth.
1932 *
1933 * These constants for the overflow check are computed by the
1934 * compiler. They are not computed at run time.
1935 *
1936 * The factor of 0x7ff is added/subtracted to avoid a
1937 * rounding error in the wrong direction when the compiler
1938 * computes these constants. There is rounding because an
1939 * 64-bit integer has 63 bits of precision where a double
1940 * only has 53 bits. Without the 0x7ff factor, the compiler
1941 * may round up and produce a double for the bounds check
1942 * that is larger than can be stored in a 64-bit integer. The
1943 * amoutn of 0x7ff is picked because it has 11 bits set.
1944 *
1945 * Without the 0x7ff there is a ~30 minute range of time
1946 * values 10 billion years in the past and in the future
1947 * where this code could go wrong. Some compilers correctly
1948 * generate a warning or error without the 0x7ff.
1949 */
1950 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1951 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1952
1953 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001954 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 goto Done;
1956 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001957
1958 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001960 pDecodedItem->val.epochDate.fSecondsFraction =
1961 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001963#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001964
Laurence Lundbladec7114722020-08-13 05:11:40 -07001965 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001966 goto Done;
1967
Laurence Lundblade9682a532020-06-06 18:33:04 -07001968#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001969 break;
1970
1971 default:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001972 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001973 goto Done;
1974 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001975
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1977
1978Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001979 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001980}
1981
1982
1983#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade123224b2021-01-03 20:58:06 -08001984/**
Laurence Lundbladee176d852021-01-03 17:50:30 -08001985 * @brief Decode decimal fractions and big floats.
1986 *
Laurence Lundblade123224b2021-01-03 20:58:06 -08001987 * @param[in] pMe The decode context.
Laurence Lundbladee176d852021-01-03 17:50:30 -08001988 * @param[in,out] pDecodedItem On input the array data item that
1989 * holds the mantissa and exponent. On
1990 * output the decoded mantissa and
1991 * exponent.
1992 *
1993 * @returns Decoding errors from getting primitive data items or
1994 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
1995 *
1996 * When called pDecodedItem must be the array that is tagged as a big
1997 * float or decimal fraction, the array that has the two members, the
1998 * exponent and mantissa.
1999 *
2000 * This will fetch and decode the exponent and mantissa and put the
2001 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002002 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002003static inline QCBORError
Laurence Lundblade123224b2021-01-03 20:58:06 -08002004QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002005{
Laurence Lundbladee176d852021-01-03 17:50:30 -08002006 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007
Laurence Lundbladee176d852021-01-03 17:50:30 -08002008 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002010 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002011 goto Done;
2012 }
2013
Laurence Lundbladee176d852021-01-03 17:50:30 -08002014 /* A check for pDecodedItem->val.uCount == 2 would work for
2015 * definite length arrays, but not for indefnite. Instead remember
2016 * the nesting level the two integers must be at, which is one
2017 * deeper than that of the array.
2018 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002019 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2020
Laurence Lundbladee176d852021-01-03 17:50:30 -08002021 /* --- Which is it, ecimal fraction or a bigfloat? --- */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002022 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002023 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2024
Laurence Lundbladee176d852021-01-03 17:50:30 -08002025 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 QCBORItem exponentItem;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002027 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundbladee176d852021-01-03 17:50:30 -08002028 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002029 goto Done;
2030 }
2031 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002032 /* Array is empty or a map/array encountered when expecting an int */
2033 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 goto Done;
2035 }
2036 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002037 /* Data arriving as an unsigned int < INT64_MAX has been
2038 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2039 * also means that the only data arriving here of type
2040 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2041 * and thus an error that will get handled in the next else.
2042 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2044 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002045 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2046 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047 goto Done;
2048 }
2049
Laurence Lundbladee176d852021-01-03 17:50:30 -08002050 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051 QCBORItem mantissaItem;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002052 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
Laurence Lundbladee176d852021-01-03 17:50:30 -08002053 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002054 goto Done;
2055 }
2056 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002057 /* Mantissa missing or map/array encountered when expecting number */
2058 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 goto Done;
2060 }
2061 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002062 /* Data arriving as an unsigned int < INT64_MAX has been
2063 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2064 * also means that the only data arriving here of type
2065 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2066 * and thus an error that will get handled in an else below.
2067 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002068 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002069 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2070 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002071 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002072 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundbladee176d852021-01-03 17:50:30 -08002073 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002074 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2075 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2076 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002078 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2079 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002080 goto Done;
2081 }
2082
Laurence Lundbladee176d852021-01-03 17:50:30 -08002083 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002084 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002085 /* Extra items in the decimal fraction / big float */
2086 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002087 goto Done;
2088 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002089 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090
2091Done:
Laurence Lundbladee176d852021-01-03 17:50:30 -08002092 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002093}
2094#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2095
2096
Laurence Lundblade123224b2021-01-03 20:58:06 -08002097/**
2098 * @brief Decode the MIME type tag
2099 *
2100 * @param[in,out] pDecodedItem The item to decode.
2101 *
2102 * Handle the text and binary MIME type tags. Slightly too complicated
2103 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2104 * incorreclty text-only.
2105 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002106static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002107{
2108 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2109 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002110 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002111 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2112 } else {
2113 return QCBOR_ERR_BAD_OPT_TAG;
2114 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002115
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002116 return QCBOR_SUCCESS;
2117}
2118
2119
Laurence Lundblade123224b2021-01-03 20:58:06 -08002120/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002121 * Table of CBOR tags whose content is either a text string or a byte
2122 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2123 * of uQCBORtype indicates the content should be a byte string rather
2124 * than a text string
2125 */
2126struct StringTagMapEntry {
2127 uint16_t uTagNumber;
2128 uint8_t uQCBORtype;
2129};
2130
2131#define IS_BYTE_STRING_BIT 0x80
2132#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2133
2134static const struct StringTagMapEntry StringTagMap[] = {
2135 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
2136 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2137 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2138 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2139 {CBOR_TAG_URI, QCBOR_TYPE_URI},
2140 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2141 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2142 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2143 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
2144 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2145 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2146};
2147
2148
Laurence Lundblade123224b2021-01-03 20:58:06 -08002149/**
2150 * @brief Process standard CBOR tags whose content is a string
2151 *
2152 * @param[in] uTag The tag.
2153 * @param[in,out] pDecodedItem The data item.
2154 *
2155 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2156 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2157 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2158 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002159 * Process the CBOR tags that whose content is a byte string or a text
2160 * string and for which the string is just passed on to the caller.
2161 *
2162 * This maps the CBOR tag to the QCBOR type and checks the content
2163 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002164 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002165 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002166 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002167static inline QCBORError
2168ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002169{
Laurence Lundblade99615302020-11-29 11:19:47 -08002170 /* This only works on tags that were not mapped; no need for other yet */
2171 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2172 return QCBOR_ERR_UNSUPPORTED;
2173 }
2174
2175 unsigned uIndex;
2176 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2177 if(StringTagMap[uIndex].uTagNumber == uTag) {
2178 break;
2179 }
2180 }
2181
2182 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2183 if(uQCBORType == QCBOR_TYPE_NONE) {
2184 /* repurpose this error to mean, not handled here */
2185 return QCBOR_ERR_UNSUPPORTED;
2186 }
2187
2188 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2189 if(uQCBORType & IS_BYTE_STRING_BIT) {
2190 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2191 }
2192
2193 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002194 return QCBOR_ERR_BAD_OPT_TAG;
2195 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002196
Laurence Lundblade99615302020-11-29 11:19:47 -08002197 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002198 return QCBOR_SUCCESS;
2199}
2200
2201
Laurence Lundblade123224b2021-01-03 20:58:06 -08002202/**
2203 * @brief Decode tag content for select tags (decoding layer 1).
2204 *
2205 * @param[in] pMe The decode context.
2206 * @param[out] pDecodedItem The decoded item.
2207 *
2208 * @return Decoding error code.
2209 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002210 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2211 * but the whole tag was not decoded. Here, the whole tags (tag number
2212 * and tag content) that are supported by QCBOR are decoded. This is a
2213 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002214 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002215static QCBORError
Laurence Lundblade7c12e252021-01-04 15:44:18 -08002216QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002217{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002218 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002219
Laurence Lundblade123224b2021-01-03 20:58:06 -08002220 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002221 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002222 goto Done;
2223 }
2224
Laurence Lundblade99615302020-11-29 11:19:47 -08002225 /* When there are no tag numbers for the item, this exits first
2226 * thing and effectively does nothing.
2227 *
2228 * This loops over all the tag numbers accumulated for this item
2229 * trying to decode and interpret them. This stops at the end of
2230 * the list or at the first tag number that can't be interpreted by
2231 * this code. This is effectively a recursive processing of the
2232 * tags number list that handles nested tags.
2233 */
2234 while(1) {
2235 /* Don't bother to unmap tags via QCBORITem.uTags since this
2236 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2237 */
2238 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002239
Laurence Lundblade99615302020-11-29 11:19:47 -08002240 if(uTagToProcess == CBOR_TAG_INVALID16) {
2241 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002242 break;
2243
Laurence Lundblade99615302020-11-29 11:19:47 -08002244 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002245 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002246
Laurence Lundblade93d89472020-10-03 22:30:50 -07002247#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002248 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2249 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade123224b2021-01-03 20:58:06 -08002250 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002251#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002252
Laurence Lundblade99615302020-11-29 11:19:47 -08002253 } else if(uTagToProcess == CBOR_TAG_MIME ||
2254 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002255 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002256
Laurence Lundblade99615302020-11-29 11:19:47 -08002257 } else {
2258 /* See if it is a pass-through byte/text string tag; process if so */
2259 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002260
Laurence Lundblade99615302020-11-29 11:19:47 -08002261 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2262 /* It wasn't a pass-through byte/text string tag so it is
2263 * an unknown tag. This is the exit from the loop on the
2264 * first unknown tag. It is a successful exit.
2265 */
2266 uReturn = QCBOR_SUCCESS;
2267 break;
2268 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002269 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002270
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002271 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002272 /* Error exit from the loop */
2273 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002274 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002275
2276 /* A tag was successfully processed, shift it out of the list of
2277 * tags returned. This is the loop increment.
2278 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002279 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002280 }
2281
2282Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002283 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002284}
2285
2286
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002287/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002288 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002289 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002290QCBORError
2291QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2292{
2293 QCBORError uErr;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08002294 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002295 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002296 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2297 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2298 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002299 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002300}
2301
2302
2303/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002304 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002305 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002306QCBORError
2307QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2308{
2309 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2310 const UsefulInputBuf Save = pMe->InBuf;
2311
2312 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2313
2314 pMe->nesting = SaveNesting;
2315 pMe->InBuf = Save;
2316
2317 return uErr;
2318}
2319
2320
2321/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002322 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002323 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002324void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2325{
2326 if(pMe->uLastError != QCBOR_SUCCESS) {
2327 return;
2328 }
2329
2330 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2331}
2332
2333
2334/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002335 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002336 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002337QCBORError
Laurence Lundblade123224b2021-01-03 20:58:06 -08002338QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2339 QCBORItem *pDecodedItem,
2340 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002341{
Laurence Lundblade123224b2021-01-03 20:58:06 -08002342 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002343
Laurence Lundblade123224b2021-01-03 20:58:06 -08002344 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2345 if(uReturn != QCBOR_SUCCESS) {
2346 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002347 }
2348
2349 if(pTags != NULL) {
2350 pTags->uNumUsed = 0;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002351 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002352 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2353 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002354 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002355 }
2356 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2357 return QCBOR_ERR_TOO_MANY_TAGS;
2358 }
Laurence Lundblade123224b2021-01-03 20:58:06 -08002359 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002360 pTags->uNumUsed++;
2361 }
2362 }
2363
2364 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002365}
2366
2367
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302368/*
Laurence Lundblade7c12e252021-01-04 15:44:18 -08002369 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002370 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002371bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002372 const QCBORItem *pItem,
2373 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002374{
Laurence Lundblade7c12e252021-01-04 15:44:18 -08002375 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002376 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002377 break;
2378 }
Laurence Lundblade123224b2021-01-03 20:58:06 -08002379 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002380 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002381 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002382 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002383
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002384 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002385}
2386
2387
2388/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002389 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002390 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002391QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002392{
Laurence Lundblade123224b2021-01-03 20:58:06 -08002393 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002394
2395 if(uReturn != QCBOR_SUCCESS) {
2396 goto Done;
2397 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002398
Laurence Lundblade123224b2021-01-03 20:58:06 -08002399 /* Error out if all the maps/arrays are not closed out */
2400 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002401 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002402 goto Done;
2403 }
2404
Laurence Lundblade123224b2021-01-03 20:58:06 -08002405 /* Error out if not all the bytes are consumed */
2406 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002407 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002409
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002410Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002411#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade123224b2021-01-03 20:58:06 -08002412 /* Call the destructor for the string allocator if there is one.
2413 * Always called, even if there are errors; always have to clean up.
2414 */
2415 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002416#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002417
Laurence Lundblade085d7952020-07-24 10:26:30 -07002418 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002419}
2420
2421
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002422/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002423 * Public function, see header qcbor/qcbor_decode.h file
2424 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002425// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002426uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2427 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002428 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002429{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002430 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2431 return CBOR_TAG_INVALID64;
2432 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002433 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2434 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002435 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002436 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002437 }
2438}
2439
Laurence Lundblade123224b2021-01-03 20:58:06 -08002440
Laurence Lundblade9b334962020-08-27 10:55:53 -07002441/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002442 * Public function, see header qcbor/qcbor_decode.h file
2443 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002444uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2445 uint32_t uIndex)
2446{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002447 if(pMe->uLastError != QCBOR_SUCCESS) {
2448 return CBOR_TAG_INVALID64;
2449 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002450 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2451 return CBOR_TAG_INVALID64;
2452 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002453 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002454 }
2455}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002456
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002457
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002458
2459
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002460#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002461
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002462/* ===========================================================================
2463 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002464
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002465 This implements a simple sting allocator for indefinite length
2466 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2467 implements the function type QCBORStringAllocate and allows easy
2468 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002469
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002470 This particular allocator is built-in for convenience. The caller
2471 can implement their own. All of this following code will get
2472 dead-stripped if QCBORDecode_SetMemPool() is not called.
2473
2474 This is a very primitive memory allocator. It does not track
2475 individual allocations, only a high-water mark. A free or
2476 reallocation must be of the last chunk allocated.
2477
2478 The size of the pool and offset to free memory are packed into the
2479 first 8 bytes of the memory pool so we don't have to keep them in
2480 the decode context. Since the address of the pool may not be
2481 aligned, they have to be packed and unpacked as if they were
2482 serialized data of the wire or such.
2483
2484 The sizes packed in are uint32_t to be the same on all CPU types
2485 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002486 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002487
2488
Laurence Lundbladeee851742020-01-08 08:37:05 -08002489static inline int
2490MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002491{
2492 // Use of UsefulInputBuf is overkill, but it is convenient.
2493 UsefulInputBuf UIB;
2494
Laurence Lundbladeee851742020-01-08 08:37:05 -08002495 // Just assume the size here. It was checked during SetUp so
2496 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002497 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002498 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2499 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2500 return UsefulInputBuf_GetError(&UIB);
2501}
2502
2503
Laurence Lundbladeee851742020-01-08 08:37:05 -08002504static inline int
2505MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002506{
2507 // Use of UsefulOutBuf is overkill, but convenient. The
2508 // length check performed here is useful.
2509 UsefulOutBuf UOB;
2510
2511 UsefulOutBuf_Init(&UOB, Pool);
2512 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2513 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2514 return UsefulOutBuf_GetError(&UOB);
2515}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002516
2517
2518/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002519 Internal function for an allocation, reallocation free and destuct.
2520
2521 Having only one function rather than one each per mode saves space in
2522 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002523
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002524 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2525 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002526static UsefulBuf
2527MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002528{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002529 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002530
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002531 uint32_t uPoolSize;
2532 uint32_t uFreeOffset;
2533
2534 if(uNewSize > UINT32_MAX) {
2535 // This allocator is only good up to 4GB. This check should
2536 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2537 goto Done;
2538 }
2539 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2540
2541 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2542 goto Done;
2543 }
2544
2545 if(uNewSize) {
2546 if(pMem) {
2547 // REALLOCATION MODE
2548 // Calculate pointer to the end of the memory pool. It is
2549 // assumed that pPool + uPoolSize won't wrap around by
2550 // assuming the caller won't pass a pool buffer in that is
2551 // not in legitimate memory space.
2552 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2553
2554 // Check that the pointer for reallocation is in the range of the
2555 // pool. This also makes sure that pointer math further down
2556 // doesn't wrap under or over.
2557 if(pMem >= pPool && pMem < pPoolEnd) {
2558 // Offset to start of chunk for reallocation. This won't
2559 // wrap under because of check that pMem >= pPool. Cast
2560 // is safe because the pool is always less than UINT32_MAX
2561 // because of check in QCBORDecode_SetMemPool().
2562 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2563
2564 // Check to see if the allocation will fit. uPoolSize -
2565 // uMemOffset will not wrap under because of check that
2566 // pMem is in the range of the uPoolSize by check above.
2567 if(uNewSize <= uPoolSize - uMemOffset) {
2568 ReturnValue.ptr = pMem;
2569 ReturnValue.len = uNewSize;
2570
2571 // Addition won't wrap around over because uNewSize was
2572 // checked to be sure it is less than the pool size.
2573 uFreeOffset = uMemOffset + uNewSize32;
2574 }
2575 }
2576 } else {
2577 // ALLOCATION MODE
2578 // uPoolSize - uFreeOffset will not underflow because this
2579 // pool implementation makes sure uFreeOffset is always
2580 // smaller than uPoolSize through this check here and
2581 // reallocation case.
2582 if(uNewSize <= uPoolSize - uFreeOffset) {
2583 ReturnValue.len = uNewSize;
2584 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002585 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002586 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002587 }
2588 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002589 if(pMem) {
2590 // FREE MODE
2591 // Cast is safe because of limit on pool size in
2592 // QCBORDecode_SetMemPool()
2593 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2594 } else {
2595 // DESTRUCT MODE
2596 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002597 }
2598 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002599
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002600 UsefulBuf Pool = {pPool, uPoolSize};
2601 MemPool_Pack(Pool, uFreeOffset);
2602
2603Done:
2604 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002605}
2606
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002607
Laurence Lundbladef6531662018-12-04 10:42:22 +09002608/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002609 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002610 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002611QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2612 UsefulBuf Pool,
2613 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002614{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002615 // The pool size and free mem offset are packed into the beginning
2616 // of the pool memory. This compile time check make sure the
2617 // constant in the header is correct. This check should optimize
2618 // down to nothing.
2619 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002620 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002621 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002622
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002623 // The pool size and free offset packed in to the beginning of pool
2624 // memory are only 32-bits. This check will optimize out on 32-bit
2625 // machines.
2626 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002627 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002628 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002629
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002630 // This checks that the pool buffer given is big enough.
2631 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002632 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002633 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002634
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002635 pMe->StringAllocator.pfAllocator = MemPool_Function;
2636 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2637 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002638
Laurence Lundblade30816f22018-11-10 13:40:22 +07002639 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002640}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002641#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002642
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002643
2644
Laurence Lundblade9b334962020-08-27 10:55:53 -07002645static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2646{
2647 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2648}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002649
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002650
2651/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002652 Consume an entire map or array (and do next to
2653 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002654 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002655static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002656ConsumeItem(QCBORDecodeContext *pMe,
2657 const QCBORItem *pItemToConsume,
2658 uint_fast8_t *puNextNestLevel)
2659{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002660 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002661 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002662
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002663 // If it is a map or array, this will tell if it is empty.
2664 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2665
2666 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2667 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002668
Laurence Lundblade1341c592020-04-11 14:19:05 -07002669 /* This works for definite and indefinite length
2670 * maps and arrays by using the nesting level
2671 */
2672 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002673 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002674 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002675 goto Done;
2676 }
2677 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002678
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002679 *puNextNestLevel = Item.uNextNestLevel;
2680
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002681 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002682
Laurence Lundblade1341c592020-04-11 14:19:05 -07002683 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002684 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002685 /* Just pass the nesting level through */
2686 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2687
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002688 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002689 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002690
2691Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002692 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002693}
2694
2695
Laurence Lundblade1341c592020-04-11 14:19:05 -07002696/* Return true if the labels in Item1 and Item2 are the same.
2697 Works only for integer and string labels. Returns false
2698 for any other type. */
2699static inline bool
2700MatchLabel(QCBORItem Item1, QCBORItem Item2)
2701{
2702 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2703 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2704 return true;
2705 }
2706 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002707 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002708 return true;
2709 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002710 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002711 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2712 return true;
2713 }
2714 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2715 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2716 return true;
2717 }
2718 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002719
Laurence Lundblade1341c592020-04-11 14:19:05 -07002720 /* Other label types are never matched */
2721 return false;
2722}
2723
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002724
2725/*
2726 Returns true if Item1 and Item2 are the same type
2727 or if either are of QCBOR_TYPE_ANY.
2728 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002729static inline bool
2730MatchType(QCBORItem Item1, QCBORItem Item2)
2731{
2732 if(Item1.uDataType == Item2.uDataType) {
2733 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002734 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002735 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002736 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002737 return true;
2738 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002739 return false;
2740}
2741
2742
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002743/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002744 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002745
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002746 @param[in] pMe The decode context to search.
2747 @param[in,out] pItemArray The items to search for and the items found.
2748 @param[out] puOffset Byte offset of last item matched.
2749 @param[in] pCBContext Context for the not-found item call back.
2750 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002751
2752 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2753
Laurence Lundblade93d89472020-10-03 22:30:50 -07002754 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2755 were found for one of the labels being
2756 search for. This duplicate detection is
2757 only performed for items in pItemArray,
2758 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002759
Laurence Lundblade93d89472020-10-03 22:30:50 -07002760 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2761 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002762
2763 @retval Also errors returned by QCBORDecode_GetNext().
2764
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002765 On input pItemArray contains a list of labels and data types
2766 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002767
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002768 On output the fully retrieved items are filled in with
2769 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002770
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002771 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002772
2773 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002774 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002775static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002776MapSearch(QCBORDecodeContext *pMe,
2777 QCBORItem *pItemArray,
2778 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002779 void *pCBContext,
2780 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002781{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002782 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002783 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002784
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002785 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002786 uReturn = pMe->uLastError;
2787 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002788 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002789
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002790 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002791 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2792 /* QCBOR_TYPE_NONE as first item indicates just looking
2793 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002794 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2795 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002796 }
2797
Laurence Lundblade085d7952020-07-24 10:26:30 -07002798 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2799 // It is an empty bounded array or map
2800 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2801 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002802 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002803 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002804 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002805 // Nothing is ever found in an empty array or map. All items
2806 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002807 uReturn = QCBOR_SUCCESS;
2808 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002809 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002810 }
2811
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002812 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002813 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2814
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002815 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816 UsefulInputBuf_Seek(&(pMe->InBuf),
2817 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002818
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002819 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002820 Loop over all the items in the map or array. Each item
2821 could be a map or array, but label matching is only at
2822 the main level. This handles definite and indefinite
2823 length maps and arrays. The only reason this is ever
2824 called on arrays is to find their end position.
2825
2826 This will always run over all items in order to do
2827 duplicate detection.
2828
2829 This will exit with failure if it encounters an
2830 unrecoverable error, but continue on for recoverable
2831 errors.
2832
2833 If a recoverable error occurs on a matched item, then
2834 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002835 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002836 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002837 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002838 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002839 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002840 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002841
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002842 /* Get the item */
2843 QCBORItem Item;
Laurence Lundblade7c12e252021-01-04 15:44:18 -08002844 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002845 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002846 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002847 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002848 goto Done;
2849 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002850 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002851 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002852 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002853 goto Done;
2854 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002855
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002856 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002857 bool bMatched = false;
2858 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2859 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002860 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002861 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2862 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002863 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002864 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002865 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002866 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002867 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002868 goto Done;
2869 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002870
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002871 if(uResult != QCBOR_SUCCESS) {
2872 uReturn = uResult;
2873 goto Done;
2874 }
2875
Laurence Lundblade1341c592020-04-11 14:19:05 -07002876 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002877 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002878 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002879 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002880 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002881 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002882 bMatched = true;
2883 }
2884 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002885
2886
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002887 if(!bMatched && pfCallback != NULL) {
2888 /*
2889 Call the callback on unmatched labels.
2890 (It is tempting to do duplicate detection here, but that would
2891 require dynamic memory allocation because the number of labels
2892 that might be encountered is unbounded.)
2893 */
2894 uReturn = (*pfCallback)(pCBContext, &Item);
2895 if(uReturn != QCBOR_SUCCESS) {
2896 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002897 }
2898 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002899
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002900 /*
2901 Consume the item whether matched or not. This
2902 does the work of traversing maps and array and
2903 everything in them. In this loop only the
2904 items at the current nesting level are examined
2905 to match the labels.
2906 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002907 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002908 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002909 goto Done;
2910 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002911
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002912 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002913
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002914 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002915
2916 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002917
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002918 // Check here makes sure that this won't accidentally be
2919 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002920 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002921 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2922 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002923 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2924 goto Done;
2925 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002926 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2927 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002928
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002929 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002930 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2931
2932 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002933 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002934 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002935 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002936 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2937 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002938 }
2939 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002940
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002941 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002942}
2943
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002944
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002945/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002946 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002947*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002948void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2949 int64_t nLabel,
2950 uint8_t uQcborType,
2951 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002952{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002953 if(pMe->uLastError != QCBOR_SUCCESS) {
2954 return;
2955 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002956
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002957 QCBORItem OneItemSeach[2];
2958 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2959 OneItemSeach[0].label.int64 = nLabel;
2960 OneItemSeach[0].uDataType = uQcborType;
2961 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002962
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002963 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002964
2965 *pItem = OneItemSeach[0];
2966
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002967 if(uReturn != QCBOR_SUCCESS) {
2968 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002969 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002970 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002971 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002972 }
2973
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002974 Done:
2975 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002976}
2977
2978
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002979/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002980 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002981*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002982void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2983 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002984 uint8_t uQcborType,
2985 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002986{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002987 if(pMe->uLastError != QCBOR_SUCCESS) {
2988 return;
2989 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002990
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002991 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002992 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2993 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2994 OneItemSeach[0].uDataType = uQcborType;
2995 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002996
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002997 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2998 if(uReturn != QCBOR_SUCCESS) {
2999 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003000 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003001 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003002 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003003 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003004 }
3005
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003006 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003007
3008Done:
3009 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003010}
3011
3012
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003013
Laurence Lundblade93d89472020-10-03 22:30:50 -07003014static QCBORError
3015CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003016{
3017 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3018 if(uDataType == puTypeList[i]) {
3019 return QCBOR_SUCCESS;
3020 }
3021 }
3022 return QCBOR_ERR_UNEXPECTED_TYPE;
3023}
3024
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003025
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003026/**
3027 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003028 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003029
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003030 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3031 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003032
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003033 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3034 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003035 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003036static QCBORError
3037CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003038{
3039 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3040 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3041 /* There are tags that QCBOR couldn't process on this item and
3042 the caller has told us there should not be. */
3043 return QCBOR_ERR_UNEXPECTED_TYPE;
3044 }
3045
3046 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3047 const int nItemType = pItem->uDataType;
3048
3049 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3050 // Must match the tag and only the tag
3051 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3052 }
3053
3054 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3055 if(uReturn == QCBOR_SUCCESS) {
3056 return QCBOR_SUCCESS;
3057 }
3058
3059 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3060 /* Must match the content type and only the content type.
3061 There was no match just above so it is a fail. */
3062 return QCBOR_ERR_UNEXPECTED_TYPE;
3063 }
3064
3065 /* If here it can match either the tag or the content
3066 and it hasn't matched the content, so the end
3067 result is whether it matches the tag. This is
3068 also the case that the CBOR standard discourages. */
3069
3070 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3071}
3072
Laurence Lundblade9b334962020-08-27 10:55:53 -07003073
Laurence Lundblade9b334962020-08-27 10:55:53 -07003074
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003075// This could be semi-private if need be
3076static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003077void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3078 int64_t nLabel,
3079 TagSpecification TagSpec,
3080 QCBORItem *pItem)
3081{
3082 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3083 if(pMe->uLastError != QCBOR_SUCCESS) {
3084 return;
3085 }
3086
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003087 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003088}
3089
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003090
3091// This could be semi-private if need be
3092static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003093void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3094 const char *szLabel,
3095 TagSpecification TagSpec,
3096 QCBORItem *pItem)
3097{
3098 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3099 if(pMe->uLastError != QCBOR_SUCCESS) {
3100 return;
3101 }
3102
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003103 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003104}
3105
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003106// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003107void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3108 int64_t nLabel,
3109 TagSpecification TagSpec,
3110 UsefulBufC *pString)
3111{
3112 QCBORItem Item;
3113 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3114 if(pMe->uLastError == QCBOR_SUCCESS) {
3115 *pString = Item.val.string;
3116 }
3117}
3118
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003119// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003120void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3121 const char * szLabel,
3122 TagSpecification TagSpec,
3123 UsefulBufC *pString)
3124{
3125 QCBORItem Item;
3126 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3127 if(pMe->uLastError == QCBOR_SUCCESS) {
3128 *pString = Item.val.string;
3129 }
3130}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003131
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003132/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003133 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003134*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003135void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003136{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003137 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3138 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003139}
3140
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_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3145 QCBORItem *pItemList,
3146 void *pCallbackCtx,
3147 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003148{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003149 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3150 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003151}
3152
3153
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003154/**
3155 * @brief Search for a map/array by label and enter it
3156 *
3157 * @param[in] pMe The decode context.
3158 * @param[in] pSearch The map/array to search for.
3159 *
3160 * @c pSearch is expected to contain one item of type map or array
3161 * with the label specified. The current bounded map will be searched for
3162 * this and if found will be entered.
3163 *
3164 * If the label is not found, or the item found is not a map or array,
3165 * the error state is set.
3166 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003167static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003168{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003169 // The first item in pSearch is the one that is to be
3170 // entered. It should be the only one filled in. Any other
3171 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003172 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003173 return;
3174 }
3175
3176 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003177 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003178 if(pMe->uLastError != QCBOR_SUCCESS) {
3179 return;
3180 }
3181
Laurence Lundblade9b334962020-08-27 10:55:53 -07003182 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003183 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003184 return;
3185 }
3186
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003187 /*
3188 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3189 * next item for the pre-order traversal cursor to be the map/array
3190 * found by MapSearch(). The next few lines of code force the
3191 * cursor to that.
3192 *
3193 * There is no need to retain the old cursor because
3194 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3195 * beginning of the map/array being entered.
3196 *
3197 * The cursor is forced by: 1) setting the input buffer position to
3198 * the item offset found by MapSearch(), 2) setting the map/array
3199 * counter to the total in the map/array, 3) setting the nesting
3200 * level. Setting the map/array counter to the total is not
3201 * strictly correct, but this is OK because this cursor only needs
3202 * to be used to get one item and MapSearch() has already found it
3203 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003204 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003205 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003206
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003207 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3208
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003209 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003210
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003211 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003212}
3213
3214
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003215/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003216 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003217*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003218void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003219{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003220 QCBORItem OneItemSeach[2];
3221 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3222 OneItemSeach[0].label.int64 = nLabel;
3223 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3224 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003225
Laurence Lundblade9b334962020-08-27 10:55:53 -07003226 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003227 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003228}
3229
3230
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003231/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003232 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003233*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003234void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003235{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003236 QCBORItem OneItemSeach[2];
3237 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3238 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3239 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3240 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003241
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003242 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003243}
3244
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003245/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003246 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003247*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003248void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003249{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003250 QCBORItem OneItemSeach[2];
3251 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3252 OneItemSeach[0].label.int64 = nLabel;
3253 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3254 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003255
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003256 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003257}
3258
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003259/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003260 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003261*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003262void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3263{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003264 QCBORItem OneItemSeach[2];
3265 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3266 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3267 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3268 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003269
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003270 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003271}
3272
3273
Laurence Lundblade02625d42020-06-25 14:41:41 -07003274// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003275void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003276{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003277 QCBORError uErr;
3278
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003279 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003280 if(pMe->uLastError != QCBOR_SUCCESS) {
3281 // Already in error state; do nothing.
3282 return;
3283 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003284
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003285 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003286 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003287 uErr = QCBORDecode_GetNext(pMe, &Item);
3288 if(uErr != QCBOR_SUCCESS) {
3289 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003290 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003291 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003292 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3293 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003294 }
3295
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003296 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003297
3298
Laurence Lundbladef0499502020-08-01 11:55:57 -07003299 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003300 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003301 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3302 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003303 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003304 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3305 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003306 // Special case to increment nesting level for zero-length maps
3307 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003308 DecodeNesting_Descend(&(pMe->nesting), uType);
3309 }
3310
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003311 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003312
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003313 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3314 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003315
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003316 if(pItem != NULL) {
3317 *pItem = Item;
3318 }
3319
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003320Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003321 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003322}
3323
Laurence Lundblade02625d42020-06-25 14:41:41 -07003324
3325/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003326 This is the common work for exiting a level that is a bounded map,
3327 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003328
3329 One chunk of work is to set up the pre-order traversal so it is at
3330 the item just after the bounded map, array or bstr that is being
3331 exited. This is somewhat complex.
3332
3333 The other work is to level-up the bounded mode to next higest bounded
3334 mode or the top level if there isn't one.
3335 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003336static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003337ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003338{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003339 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003340
Laurence Lundblade02625d42020-06-25 14:41:41 -07003341 /*
3342 First the pre-order-traversal byte offset is positioned to the
3343 item just after the bounded mode item that was just consumed.
3344 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003345 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3346
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347 /*
3348 Next, set the current nesting level to one above the bounded level
3349 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003350
Laurence Lundblade02625d42020-06-25 14:41:41 -07003351 DecodeNesting_CheckBoundedType() is always called before this and
3352 makes sure pCurrentBounded is valid.
3353 */
3354 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3355
3356 /*
3357 This does the complex work of leveling up the pre-order traversal
3358 when the end of a map or array or another bounded level is
3359 reached. It may do nothing, or ascend all the way to the top
3360 level.
3361 */
Laurence Lundblade7c12e252021-01-04 15:44:18 -08003362 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003363 if(uErr != QCBOR_SUCCESS) {
3364 goto Done;
3365 }
3366
Laurence Lundblade02625d42020-06-25 14:41:41 -07003367 /*
3368 This makes the next highest bounded level the current bounded
3369 level. If there is no next highest level, then no bounded mode is
3370 in effect.
3371 */
3372 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003373
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003374 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003375
3376Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003377 return uErr;
3378}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003379
Laurence Lundblade02625d42020-06-25 14:41:41 -07003380
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003381// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003383{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003384 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003385 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003386 return;
3387 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003388
Laurence Lundblade02625d42020-06-25 14:41:41 -07003389 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003390
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003391 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003392 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003393 goto Done;
3394 }
3395
Laurence Lundblade02625d42020-06-25 14:41:41 -07003396 /*
3397 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003398 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003399 from previous map search, then do a dummy search.
3400 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003401 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003402 QCBORItem Dummy;
3403 Dummy.uLabelType = QCBOR_TYPE_NONE;
3404 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3405 if(uErr != QCBOR_SUCCESS) {
3406 goto Done;
3407 }
3408 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003409
Laurence Lundblade02625d42020-06-25 14:41:41 -07003410 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003411
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003412Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003413 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003414}
3415
3416
Laurence Lundblade1341c592020-04-11 14:19:05 -07003417
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003418static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003419 const QCBORItem *pItem,
3420 uint8_t uTagRequirement,
3421 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003422{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003423 if(pBstr) {
3424 *pBstr = NULLUsefulBufC;
3425 }
3426
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003427 if(pMe->uLastError != QCBOR_SUCCESS) {
3428 // Already in error state; do nothing.
3429 return pMe->uLastError;
3430 }
3431
3432 QCBORError uError = QCBOR_SUCCESS;
3433
3434 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3435 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3436 goto Done;;
3437 }
3438
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003439 const TagSpecification TagSpec =
3440 {
3441 uTagRequirement,
3442 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3443 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3444 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003445
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003446 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003447 if(uError != QCBOR_SUCCESS) {
3448 goto Done;
3449 }
3450
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003451 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003452 // Reverse the decrement done by GetNext() for the bstr so the
Laurence Lundblade7c12e252021-01-04 15:44:18 -08003453 // increment in QCBORDecode_NestLevelAscender() called by ExitBoundedLevel()
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003454 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003455 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003456 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003457
3458 if(pBstr) {
3459 *pBstr = pItem->val.string;
3460 }
3461
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003462 // This saves the current length of the UsefulInputBuf and then
3463 // narrows the UsefulInputBuf to start and length of the wrapped
3464 // CBOR that is being entered.
3465 //
3466 // This makes sure the length is less than
3467 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3468 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3469 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3470 // the casts safe. uEndOfBstr will always be less than
3471 // uPreviousLength because of the way UsefulInputBuf works so there
3472 // is no need to check it. There is also a range check in the
3473 // seek.
3474 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003475 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003476 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003477 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003478 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003479 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003480 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003481 goto Done;
3482 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003483 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003484 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003485 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003486
Laurence Lundblade02625d42020-06-25 14:41:41 -07003487 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003488 (uint32_t)uPreviousLength,
3489 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003490Done:
3491 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003492}
3493
3494
Laurence Lundblade02625d42020-06-25 14:41:41 -07003495/*
3496 Public function, see header qcbor/qcbor_decode.h file
3497 */
3498void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003499 uint8_t uTagRequirement,
3500 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003501{
3502 if(pMe->uLastError != QCBOR_SUCCESS) {
3503 // Already in error state; do nothing.
3504 return;
3505 }
3506
3507 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003508 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003509 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3510 if(pMe->uLastError != QCBOR_SUCCESS) {
3511 return;
3512 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003513
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003514 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003515 &Item,
3516 uTagRequirement,
3517 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003518}
3519
3520
Laurence Lundblade02625d42020-06-25 14:41:41 -07003521/*
3522 Public function, see header qcbor/qcbor_decode.h file
3523 */
3524void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003525 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003526 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003527 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003528{
3529 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003530 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003531
Laurence Lundblade93d89472020-10-03 22:30:50 -07003532 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3533 &Item,
3534 uTagRequirement,
3535 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003536}
3537
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003538
Laurence Lundblade02625d42020-06-25 14:41:41 -07003539/*
3540 Public function, see header qcbor/qcbor_decode.h file
3541 */
3542void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003543 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003544 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003545 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003546{
3547 QCBORItem Item;
3548 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3549
Laurence Lundblade93d89472020-10-03 22:30:50 -07003550 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3551 &Item,
3552 uTagRequirement,
3553 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003554}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003555
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003556
Laurence Lundblade02625d42020-06-25 14:41:41 -07003557/*
3558 Public function, see header qcbor/qcbor_decode.h file
3559 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003560void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003561{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003562 if(pMe->uLastError != QCBOR_SUCCESS) {
3563 // Already in error state; do nothing.
3564 return;
3565 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003566
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003567 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003568 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003569 return;
3570 }
3571
3572 /*
3573 Reset the length of the UsefulInputBuf to what it was before
3574 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003575 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003576 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003577 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003578
3579
Laurence Lundblade02625d42020-06-25 14:41:41 -07003580 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003581 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003582}
3583
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003584
Laurence Lundbladee6430642020-03-14 21:15:44 -07003585
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003586
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003587
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003588
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003589
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003590
Laurence Lundblade93d89472020-10-03 22:30:50 -07003591static QCBORError
3592InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593{
3594 switch(pItem->uDataType) {
3595 case QCBOR_TYPE_TRUE:
3596 *pBool = true;
3597 return QCBOR_SUCCESS;
3598 break;
3599
3600 case QCBOR_TYPE_FALSE:
3601 *pBool = false;
3602 return QCBOR_SUCCESS;
3603 break;
3604
3605 default:
3606 return QCBOR_ERR_UNEXPECTED_TYPE;
3607 break;
3608 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003609 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003610}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003611
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003612
Laurence Lundblade9b334962020-08-27 10:55:53 -07003613
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003614/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003615 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003616*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003617void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003618{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003619 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003620 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003621 return;
3622 }
3623
Laurence Lundbladec4537442020-04-14 18:53:22 -07003624 QCBORError nError;
3625 QCBORItem Item;
3626
3627 nError = QCBORDecode_GetNext(pMe, &Item);
3628 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003629 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003630 return;
3631 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003632 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003633}
3634
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003635
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003636/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003637 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003638*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003639void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003640{
3641 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003642 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003643
Laurence Lundblade9b334962020-08-27 10:55:53 -07003644 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003645}
3646
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003647
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003648/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003649 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003650*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003651void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3652{
3653 QCBORItem Item;
3654 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3655
Laurence Lundblade9b334962020-08-27 10:55:53 -07003656 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003657}
3658
3659
3660
Laurence Lundbladec7114722020-08-13 05:11:40 -07003661
3662static void ProcessEpochDate(QCBORDecodeContext *pMe,
3663 QCBORItem *pItem,
3664 uint8_t uTagRequirement,
3665 int64_t *pnTime)
3666{
3667 if(pMe->uLastError != QCBOR_SUCCESS) {
3668 // Already in error state, do nothing
3669 return;
3670 }
3671
3672 QCBORError uErr;
3673
3674 const TagSpecification TagSpec =
3675 {
3676 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003677 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3678 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003679 };
3680
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003681 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003682 if(uErr != QCBOR_SUCCESS) {
3683 goto Done;
3684 }
3685
3686 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3687 uErr = DecodeDateEpoch(pItem);
3688 if(uErr != QCBOR_SUCCESS) {
3689 goto Done;
3690 }
3691 }
3692
Laurence Lundblade9b334962020-08-27 10:55:53 -07003693 // Save the tags in the last item's tags in the decode context
3694 // for QCBORDecode_GetNthTagOfLast()
3695 CopyTags(pMe, pItem);
3696
Laurence Lundbladec7114722020-08-13 05:11:40 -07003697 *pnTime = pItem->val.epochDate.nSeconds;
3698
3699Done:
3700 pMe->uLastError = (uint8_t)uErr;
3701}
3702
3703
3704void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003705 uint8_t uTagRequirement,
3706 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003707{
3708 if(pMe->uLastError != QCBOR_SUCCESS) {
3709 // Already in error state, do nothing
3710 return;
3711 }
3712
3713 QCBORItem Item;
3714 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3715
3716 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3717}
3718
3719
3720void
3721QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3722 int64_t nLabel,
3723 uint8_t uTagRequirement,
3724 int64_t *pnTime)
3725{
3726 QCBORItem Item;
3727 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3728 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3729}
3730
3731
3732void
3733QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3734 const char *szLabel,
3735 uint8_t uTagRequirement,
3736 int64_t *pnTime)
3737{
3738 QCBORItem Item;
3739 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3740 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3741}
3742
3743
3744
3745
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003746void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3747 TagSpecification TagSpec,
3748 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003749{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003750 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003751 // Already in error state, do nothing
3752 return;
3753 }
3754
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003755 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003756 QCBORItem Item;
3757
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003758 uError = QCBORDecode_GetNext(pMe, &Item);
3759 if(uError != QCBOR_SUCCESS) {
3760 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003761 return;
3762 }
3763
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003764 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003765
3766 if(pMe->uLastError == QCBOR_SUCCESS) {
3767 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003768 } else {
3769 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770 }
3771}
3772
Laurence Lundbladec4537442020-04-14 18:53:22 -07003773
3774
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003775
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003776static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003777 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003778 UsefulBufC *pValue,
3779 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003780{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003781 const TagSpecification TagSpec =
3782 {
3783 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003784 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3785 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003786 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003787
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003788 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003789 if(uErr != QCBOR_SUCCESS) {
3790 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003791 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003792
3793 *pValue = pItem->val.string;
3794
3795 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3796 *pbIsNegative = false;
3797 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3798 *pbIsNegative = true;
3799 }
3800
3801 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003802}
3803
3804
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003805/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003806 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003807 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003808void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3809 uint8_t uTagRequirement,
3810 UsefulBufC *pValue,
3811 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003812{
3813 if(pMe->uLastError != QCBOR_SUCCESS) {
3814 // Already in error state, do nothing
3815 return;
3816 }
3817
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003818 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003819 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3820 if(uError != QCBOR_SUCCESS) {
3821 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003822 return;
3823 }
3824
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003825 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003826}
3827
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003828
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003829/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003830 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003831*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003832void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3833 int64_t nLabel,
3834 uint8_t uTagRequirement,
3835 UsefulBufC *pValue,
3836 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003837{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003838 QCBORItem Item;
3839 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003840 if(pMe->uLastError != QCBOR_SUCCESS) {
3841 return;
3842 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003843
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003844 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003845}
3846
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003847
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003848/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003849 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003850*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003851void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3852 const char *szLabel,
3853 uint8_t uTagRequirement,
3854 UsefulBufC *pValue,
3855 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003856{
3857 QCBORItem Item;
3858 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003859 if(pMe->uLastError != QCBOR_SUCCESS) {
3860 return;
3861 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003862
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003863 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003864}
3865
3866
3867
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003868
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003869// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003870QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3871 const QCBORItem *pItem,
3872 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003873 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003874{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003875 const TagSpecification TagSpecText =
3876 {
3877 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003878 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3879 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003880 };
3881 const TagSpecification TagSpecBinary =
3882 {
3883 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003884 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3885 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003886 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003887
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003888 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003889
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003890 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003891 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003892 if(pbIsTag257 != NULL) {
3893 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003894 }
3895 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003896 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003897 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003898 if(pbIsTag257 != NULL) {
3899 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003900 }
3901 uReturn = QCBOR_SUCCESS;
3902
3903 } else {
3904 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3905 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003906
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003907 return uReturn;
3908}
3909
Laurence Lundblade93d89472020-10-03 22:30:50 -07003910// Improvement: add methods for wrapped CBOR, a simple alternate
3911// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003912
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003913
3914
3915
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003916#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003918typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003919
3920
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003921// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003922static QCBORError
3923Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003924{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003925 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003926
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003927 if(uResult != 0) {
3928 /* This loop will run a maximum of 19 times because
3929 * UINT64_MAX < 10 ^^ 19. More than that will cause
3930 * exit with the overflow error
3931 */
3932 for(; nExponent > 0; nExponent--) {
3933 if(uResult > UINT64_MAX / 10) {
3934 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3935 }
3936 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003937 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003938
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003939 for(; nExponent < 0; nExponent++) {
3940 uResult = uResult / 10;
3941 if(uResult == 0) {
3942 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3943 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003944 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003945 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003946 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003947
3948 *puResult = uResult;
3949
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003950 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003951}
3952
3953
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003954// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003955static QCBORError
3956Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003958 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003959
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003960 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003961
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003962 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003963 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003964 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003965 */
3966 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003967 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003968 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003969 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003970 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003971 nExponent--;
3972 }
3973
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003974 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003975 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003976 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3977 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003978 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003979 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003980 }
3981
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003982 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003983
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003984 return QCBOR_SUCCESS;
3985}
3986
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003987
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003988/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003989 Compute value with signed mantissa and signed result. Works with
3990 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003991 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003992static inline QCBORError ExponentiateNN(int64_t nMantissa,
3993 int64_t nExponent,
3994 int64_t *pnResult,
3995 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003996{
3997 uint64_t uResult;
3998
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003999 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004000 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004001 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4002
4003 // Do the exponentiation of the positive mantissa
4004 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4005 if(uReturn) {
4006 return uReturn;
4007 }
4008
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004009
Laurence Lundblade983500d2020-05-14 11:49:34 -07004010 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4011 of INT64_MIN. This assumes two's compliment representation where
4012 INT64_MIN is one increment farther from 0 than INT64_MAX.
4013 Trying to write -INT64_MIN doesn't work to get this because the
4014 compiler tries to work with an int64_t which can't represent
4015 -INT64_MIN.
4016 */
4017 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4018
4019 // Error out if too large
4020 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004021 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4022 }
4023
4024 // Casts are safe because of checks above
4025 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4026
4027 return QCBOR_SUCCESS;
4028}
4029
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004030
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004031/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004032 Compute value with signed mantissa and unsigned result. Works with
4033 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004034 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004035static inline QCBORError ExponentitateNU(int64_t nMantissa,
4036 int64_t nExponent,
4037 uint64_t *puResult,
4038 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004039{
4040 if(nMantissa < 0) {
4041 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4042 }
4043
4044 // Cast to unsigned is OK because of check for negative
4045 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4046 // Exponentiation is straight forward
4047 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4048}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004049
4050
4051/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004052 Compute value with signed mantissa and unsigned result. Works with
4053 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004054 */
4055static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4056 int64_t nExponent,
4057 uint64_t *puResult,
4058 fExponentiator pfExp)
4059{
4060 return (*pfExp)(uMantissa, nExponent, puResult);
4061}
4062
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004063#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4064
4065
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004066
4067
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004068
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004069static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004071 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004072
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004073 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004074 const uint8_t *pByte = BigNum.ptr;
4075 size_t uLen = BigNum.len;
4076 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004077 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004078 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004079 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004080 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004081 }
4082
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004083 *pResult = uResult;
4084 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004085}
4086
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004087
Laurence Lundblade887add82020-05-17 05:50:34 -07004088static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004089{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004090 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004091}
4092
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004093
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004094static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004095{
4096 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004097 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4098 if(uError) {
4099 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004100 }
4101 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4102 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004103 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004104}
4105
4106
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004107static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004108{
4109 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004110 /* The negative integer furthest from zero for a C int64_t is
4111 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4112 negative number in CBOR is computed as -n - 1 where n is the
4113 encoded integer, where n is what is in the variable BigNum. When
4114 converting BigNum to a uint64_t, the maximum value is thus
4115 INT64_MAX, so that when it -n - 1 is applied to it the result will
4116 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004117
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004118 -n - 1 <= INT64_MIN.
4119 -n - 1 <= -INT64_MAX - 1
4120 n <= INT64_MAX.
4121 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004122 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004123 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004124 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004125 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004126
4127 /// Now apply -n - 1. The cast is safe because
4128 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4129 // is the largest positive integer that an int64_t can
4130 // represent. */
4131 *pnResult = -(int64_t)uResult - 1;
4132
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004133 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004134}
4135
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004136
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004137
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004138
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004139
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004140/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004141Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004142
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004143\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004144
Laurence Lundblade93d89472020-10-03 22:30:50 -07004145\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4146 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004147
4148\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4149
Laurence Lundblade93d89472020-10-03 22:30:50 -07004150\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4151 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004152*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004153static QCBORError
4154ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004155{
4156 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004157 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004159#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004161 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4162 http://www.cplusplus.com/reference/cmath/llround/
4163 */
4164 // Not interested in FE_INEXACT
4165 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004166 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4167 *pnValue = llround(pItem->val.dfnum);
4168 } else {
4169 *pnValue = lroundf(pItem->val.fnum);
4170 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004171 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4172 // llround() shouldn't result in divide by zero, but catch
4173 // it here in case it unexpectedly does. Don't try to
4174 // distinguish between the various exceptions because it seems
4175 // they vary by CPU, compiler and OS.
4176 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
4178 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004179 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004180 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004181#else
4182 return QCBOR_ERR_HW_FLOAT_DISABLED;
4183#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004184 break;
4185
4186 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004187 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004188 *pnValue = pItem->val.int64;
4189 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004190 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004191 }
4192 break;
4193
4194 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004195 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004196 if(pItem->val.uint64 < INT64_MAX) {
4197 *pnValue = pItem->val.int64;
4198 } else {
4199 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4200 }
4201 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004202 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004203 }
4204 break;
4205
4206 default:
4207 return QCBOR_ERR_UNEXPECTED_TYPE;
4208 }
4209 return QCBOR_SUCCESS;
4210}
4211
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004212
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004213void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004214 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004215 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004216 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004217{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004218 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004219 return;
4220 }
4221
Laurence Lundbladee6430642020-03-14 21:15:44 -07004222 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004223 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4224 if(uError) {
4225 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004226 return;
4227 }
4228
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004229 if(pItem) {
4230 *pItem = Item;
4231 }
4232
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004233 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234}
4235
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004236
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004237void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4238 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004239 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240 int64_t *pnValue,
4241 QCBORItem *pItem)
4242{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004243 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004244 if(pMe->uLastError != QCBOR_SUCCESS) {
4245 return;
4246 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004247
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004248 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004249}
4250
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004251
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004252void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4253 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004254 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004255 int64_t *pnValue,
4256 QCBORItem *pItem)
4257{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004258 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004259 if(pMe->uLastError != QCBOR_SUCCESS) {
4260 return;
4261 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004262
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004263 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004264}
4265
4266
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004267/*
4268 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004269
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004270 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004271
Laurence Lundblade93d89472020-10-03 22:30:50 -07004272 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4273 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004274
4275 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4276
Laurence Lundblade93d89472020-10-03 22:30:50 -07004277 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4278 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004279 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004280static QCBORError
4281Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004282{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004283 switch(pItem->uDataType) {
4284
4285 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004286 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004287 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004288 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004289 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004290 }
4291 break;
4292
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004293 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004294 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004295 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004296 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004297 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004298 }
4299 break;
4300
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004301#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4302 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004303 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004305 pItem->val.expAndMantissa.nExponent,
4306 pnValue,
4307 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004308 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004309 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310 }
4311 break;
4312
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004313 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004314 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004315 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004316 pItem->val.expAndMantissa.nExponent,
4317 pnValue,
4318 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004319 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004320 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004321 }
4322 break;
4323
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004324 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004325 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004326 int64_t nMantissa;
4327 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004328 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4329 if(uErr) {
4330 return uErr;
4331 }
4332 return ExponentiateNN(nMantissa,
4333 pItem->val.expAndMantissa.nExponent,
4334 pnValue,
4335 Exponentitate10);
4336 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004337 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004338 }
4339 break;
4340
4341 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004342 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004343 int64_t nMantissa;
4344 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004345 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4346 if(uErr) {
4347 return uErr;
4348 }
4349 return ExponentiateNN(nMantissa,
4350 pItem->val.expAndMantissa.nExponent,
4351 pnValue,
4352 Exponentitate10);
4353 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004354 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004355 }
4356 break;
4357
4358 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004359 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004360 int64_t nMantissa;
4361 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004362 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4363 if(uErr) {
4364 return uErr;
4365 }
4366 return ExponentiateNN(nMantissa,
4367 pItem->val.expAndMantissa.nExponent,
4368 pnValue,
4369 Exponentitate2);
4370 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004371 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004372 }
4373 break;
4374
4375 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004376 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004377 int64_t nMantissa;
4378 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004379 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4380 if(uErr) {
4381 return uErr;
4382 }
4383 return ExponentiateNN(nMantissa,
4384 pItem->val.expAndMantissa.nExponent,
4385 pnValue,
4386 Exponentitate2);
4387 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004388 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004389 }
4390 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004391#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4392
Laurence Lundbladee6430642020-03-14 21:15:44 -07004393
Laurence Lundbladec4537442020-04-14 18:53:22 -07004394 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004395 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004396}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004397
4398
Laurence Lundbladec4537442020-04-14 18:53:22 -07004399/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004400 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004401 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004402void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004403{
4404 QCBORItem Item;
4405
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004407
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004408 if(pMe->uLastError == QCBOR_SUCCESS) {
4409 // The above conversion succeeded
4410 return;
4411 }
4412
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004413 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004414 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004415 return;
4416 }
4417
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004418 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004419}
4420
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004421
4422/*
4423Public function, see header qcbor/qcbor_decode.h file
4424*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004425void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4426 int64_t nLabel,
4427 uint32_t uConvertTypes,
4428 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004429{
4430 QCBORItem Item;
4431
Laurence Lundblade93d89472020-10-03 22:30:50 -07004432 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4433 nLabel,
4434 uConvertTypes,
4435 pnValue,
4436 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004437
4438 if(pMe->uLastError == QCBOR_SUCCESS) {
4439 // The above conversion succeeded
4440 return;
4441 }
4442
4443 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4444 // The above conversion failed in a way that code below can't correct
4445 return;
4446 }
4447
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004448 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004449}
4450
4451
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452/*
4453Public function, see header qcbor/qcbor_decode.h file
4454*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004455void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4456 const char *szLabel,
4457 uint32_t uConvertTypes,
4458 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004459{
4460 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004461 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4462 szLabel,
4463 uConvertTypes,
4464 pnValue,
4465 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004466
4467 if(pMe->uLastError == QCBOR_SUCCESS) {
4468 // The above conversion succeeded
4469 return;
4470 }
4471
4472 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4473 // The above conversion failed in a way that code below can't correct
4474 return;
4475 }
4476
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004477 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004478}
4479
4480
Laurence Lundblade93d89472020-10-03 22:30:50 -07004481static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482{
4483 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004484 case QCBOR_TYPE_DOUBLE:
4485 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004486#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004487 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004488 // Can't use llround here because it will not convert values
4489 // greater than INT64_MAX and less than UINT64_MAX that
4490 // need to be converted so it is more complicated.
4491 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4492 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4493 if(isnan(pItem->val.dfnum)) {
4494 return QCBOR_ERR_FLOAT_EXCEPTION;
4495 } else if(pItem->val.dfnum < 0) {
4496 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4497 } else {
4498 double dRounded = round(pItem->val.dfnum);
4499 // See discussion in DecodeDateEpoch() for
4500 // explanation of - 0x7ff
4501 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4502 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4503 }
4504 *puValue = (uint64_t)dRounded;
4505 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004506 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004507 if(isnan(pItem->val.fnum)) {
4508 return QCBOR_ERR_FLOAT_EXCEPTION;
4509 } else if(pItem->val.fnum < 0) {
4510 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4511 } else {
4512 float fRounded = roundf(pItem->val.fnum);
4513 // See discussion in DecodeDateEpoch() for
4514 // explanation of - 0x7ff
4515 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4516 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4517 }
4518 *puValue = (uint64_t)fRounded;
4519 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004520 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004521 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4522 // round() and roundf() shouldn't result in exceptions here, but
4523 // catch them to be robust and thorough. Don't try to
4524 // distinguish between the various exceptions because it seems
4525 // they vary by CPU, compiler and OS.
4526 return QCBOR_ERR_FLOAT_EXCEPTION;
4527 }
4528
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529 } else {
4530 return QCBOR_ERR_UNEXPECTED_TYPE;
4531 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004532#else
4533 return QCBOR_ERR_HW_FLOAT_DISABLED;
4534#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004535 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004536
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004537 case QCBOR_TYPE_INT64:
4538 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4539 if(pItem->val.int64 >= 0) {
4540 *puValue = (uint64_t)pItem->val.int64;
4541 } else {
4542 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4543 }
4544 } else {
4545 return QCBOR_ERR_UNEXPECTED_TYPE;
4546 }
4547 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004549 case QCBOR_TYPE_UINT64:
4550 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4551 *puValue = pItem->val.uint64;
4552 } else {
4553 return QCBOR_ERR_UNEXPECTED_TYPE;
4554 }
4555 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004557 default:
4558 return QCBOR_ERR_UNEXPECTED_TYPE;
4559 }
4560
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561 return QCBOR_SUCCESS;
4562}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004563
4564
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004565void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004566 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004568 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004569{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004570 if(pMe->uLastError != QCBOR_SUCCESS) {
4571 return;
4572 }
4573
Laurence Lundbladec4537442020-04-14 18:53:22 -07004574 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004575
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004576 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4577 if(uError) {
4578 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004579 return;
4580 }
4581
Laurence Lundbladea826c502020-05-10 21:07:00 -07004582 if(pItem) {
4583 *pItem = Item;
4584 }
4585
Laurence Lundblade93d89472020-10-03 22:30:50 -07004586 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004587}
4588
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004589
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004590void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004592 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004593 uint64_t *puValue,
4594 QCBORItem *pItem)
4595{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004596 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004597 if(pMe->uLastError != QCBOR_SUCCESS) {
4598 return;
4599 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600
Laurence Lundblade93d89472020-10-03 22:30:50 -07004601 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602}
4603
4604
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004605void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004606 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608 uint64_t *puValue,
4609 QCBORItem *pItem)
4610{
4611 if(pMe->uLastError != QCBOR_SUCCESS) {
4612 return;
4613 }
4614
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004615 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004616 if(pMe->uLastError != QCBOR_SUCCESS) {
4617 return;
4618 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004619
Laurence Lundblade93d89472020-10-03 22:30:50 -07004620 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004621}
4622
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004623
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004624
Laurence Lundblade93d89472020-10-03 22:30:50 -07004625static QCBORError
4626UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004627{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628 switch(pItem->uDataType) {
4629
4630 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004632 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4633 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004634 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004635 }
4636 break;
4637
4638 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004639 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004640 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4641 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004642 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004643 }
4644 break;
4645
4646#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4647
4648 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004649 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004650 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004651 pItem->val.expAndMantissa.nExponent,
4652 puValue,
4653 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004654 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004655 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656 }
4657 break;
4658
4659 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004660 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004661 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4662 pItem->val.expAndMantissa.nExponent,
4663 puValue,
4664 Exponentitate2);
4665 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004667 }
4668 break;
4669
4670 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004671 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004672 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004673 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004674 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 if(uErr != QCBOR_SUCCESS) {
4676 return uErr;
4677 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004678 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679 pItem->val.expAndMantissa.nExponent,
4680 puValue,
4681 Exponentitate10);
4682 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004683 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004684 }
4685 break;
4686
4687 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004688 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004689 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4690 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004691 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692 }
4693 break;
4694
4695 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004696 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004697 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004698 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004699 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700 if(uErr != QCBOR_SUCCESS) {
4701 return uErr;
4702 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004703 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004704 pItem->val.expAndMantissa.nExponent,
4705 puValue,
4706 Exponentitate2);
4707 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004708 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004709 }
4710 break;
4711
4712 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004713 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4715 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004716 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717 }
4718 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004719#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720 default:
4721 return QCBOR_ERR_UNEXPECTED_TYPE;
4722 }
4723}
4724
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004725
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004726/*
4727 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004728 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004729void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004730{
4731 QCBORItem Item;
4732
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004733 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004734
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004735 if(pMe->uLastError == QCBOR_SUCCESS) {
4736 // The above conversion succeeded
4737 return;
4738 }
4739
4740 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4741 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004742 return;
4743 }
4744
Laurence Lundblade93d89472020-10-03 22:30:50 -07004745 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004746}
4747
Laurence Lundbladec4537442020-04-14 18:53:22 -07004748
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004750 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004752void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004753 int64_t nLabel,
4754 uint32_t uConvertTypes,
4755 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004756{
4757 QCBORItem Item;
4758
Laurence Lundblade93d89472020-10-03 22:30:50 -07004759 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4760 nLabel,
4761 uConvertTypes,
4762 puValue,
4763 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764
4765 if(pMe->uLastError == QCBOR_SUCCESS) {
4766 // The above conversion succeeded
4767 return;
4768 }
4769
4770 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4771 // The above conversion failed in a way that code below can't correct
4772 return;
4773 }
4774
Laurence Lundblade93d89472020-10-03 22:30:50 -07004775 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004776}
4777
4778
4779/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004780 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004782void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004783 const char *szLabel,
4784 uint32_t uConvertTypes,
4785 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786{
4787 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004788 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4789 szLabel,
4790 uConvertTypes,
4791 puValue,
4792 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793
4794 if(pMe->uLastError == QCBOR_SUCCESS) {
4795 // The above conversion succeeded
4796 return;
4797 }
4798
4799 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4800 // The above conversion failed in a way that code below can't correct
4801 return;
4802 }
4803
Laurence Lundblade93d89472020-10-03 22:30:50 -07004804 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805}
4806
4807
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004808
4809
Laurence Lundblade9b334962020-08-27 10:55:53 -07004810static QCBORError ConvertDouble(const QCBORItem *pItem,
4811 uint32_t uConvertTypes,
4812 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004813{
4814 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004815 case QCBOR_TYPE_FLOAT:
4816#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4817 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4818 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004819 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004820 *pdValue = (double)pItem->val.fnum;
4821 } else {
4822 return QCBOR_ERR_UNEXPECTED_TYPE;
4823 }
4824 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004825#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004826 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004827#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004828 break;
4829
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4832 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 *pdValue = pItem->val.dfnum;
4834 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 }
4837 }
4838 break;
4839
4840 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004841#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004842 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004843 // A simple cast seems to do the job with no worry of exceptions.
4844 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004845 *pdValue = (double)pItem->val.int64;
4846
4847 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004848 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004850#else
4851 return QCBOR_ERR_HW_FLOAT_DISABLED;
4852#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853 break;
4854
4855 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004856#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004858 // A simple cast seems to do the job with no worry of exceptions.
4859 // There will be precision loss for some values.
4860 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 }
4864 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004865#else
4866 return QCBOR_ERR_HW_FLOAT_DISABLED;
4867#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868
4869 default:
4870 return QCBOR_ERR_UNEXPECTED_TYPE;
4871 }
4872
4873 return QCBOR_SUCCESS;
4874}
4875
4876
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004877void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004878 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004880 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004881{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004882 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004883 return;
4884 }
4885
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004886 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004887
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004888 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004889 if(uError) {
4890 pMe->uLastError = (uint8_t)uError;
4891 return;
4892 }
4893
4894 if(pItem) {
4895 *pItem = Item;
4896 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004897
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004898 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004899}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004900
Laurence Lundbladec4537442020-04-14 18:53:22 -07004901
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4903 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004904 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905 double *pdValue,
4906 QCBORItem *pItem)
4907{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004908 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004909 if(pMe->uLastError != QCBOR_SUCCESS) {
4910 return;
4911 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914}
4915
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004916
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004917void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4918 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004919 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004920 double *pdValue,
4921 QCBORItem *pItem)
4922{
4923 if(pMe->uLastError != QCBOR_SUCCESS) {
4924 return;
4925 }
4926
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004927 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004928 if(pMe->uLastError != QCBOR_SUCCESS) {
4929 return;
4930 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004931
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004932 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004933}
4934
4935
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004936#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004937static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4938{
4939 double dResult;
4940
4941 dResult = 0.0;
4942 const uint8_t *pByte = BigNum.ptr;
4943 size_t uLen = BigNum.len;
4944 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004945 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004946 while(uLen--) {
4947 dResult = (dResult * 256.0) + (double)*pByte++;
4948 }
4949
4950 return dResult;
4951}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004952#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4953
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004954
Laurence Lundblade93d89472020-10-03 22:30:50 -07004955static QCBORError
4956DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004957{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004958#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004959 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004960 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4961
4962 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004964
4965#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004966 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004967 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004968 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004969 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4970 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4971 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004972 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973 }
4974 break;
4975
4976 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004977 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004978 // Underflow gives 0, overflow gives infinity
4979 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4980 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004981 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004982 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004983 }
4984 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004985#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986
4987 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004988 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004989 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4990 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004991 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004992 }
4993 break;
4994
4995 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004996 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004997 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004999 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005000 }
5001 break;
5002
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005003#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005004 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005005 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005006 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5007 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5008 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005009 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005010 }
5011 break;
5012
5013 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_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_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005023 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005024 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5025 *pdValue = dMantissa * exp2((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_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005032 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005033 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005034 *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;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005039#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5040
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005041 default:
5042 return QCBOR_ERR_UNEXPECTED_TYPE;
5043 }
5044
5045 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005046
5047#else
5048 (void)pItem;
5049 (void)uConvertTypes;
5050 (void)pdValue;
5051 return QCBOR_ERR_HW_FLOAT_DISABLED;
5052#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5053
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005054}
5055
5056
5057/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005058 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005059*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005060void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5061 uint32_t uConvertTypes,
5062 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005063{
5064
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005065 QCBORItem Item;
5066
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005067 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005068
5069 if(pMe->uLastError == QCBOR_SUCCESS) {
5070 // The above conversion succeeded
5071 return;
5072 }
5073
5074 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5075 // The above conversion failed in a way that code below can't correct
5076 return;
5077 }
5078
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005079 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005080}
5081
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005082
5083/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005084 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005085*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005086void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5087 int64_t nLabel,
5088 uint32_t uConvertTypes,
5089 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005090{
5091 QCBORItem Item;
5092
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005093 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005094
5095 if(pMe->uLastError == QCBOR_SUCCESS) {
5096 // The above conversion succeeded
5097 return;
5098 }
5099
5100 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5101 // The above conversion failed in a way that code below can't correct
5102 return;
5103 }
5104
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005105 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005106}
5107
5108
5109/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005110 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005111*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005112void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5113 const char *szLabel,
5114 uint32_t uConvertTypes,
5115 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005116{
5117 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005118 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005119
5120 if(pMe->uLastError == QCBOR_SUCCESS) {
5121 // The above conversion succeeded
5122 return;
5123 }
5124
5125 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5126 // The above conversion failed in a way that code below can't correct
5127 return;
5128 }
5129
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005130 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005131}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005132
5133
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005134
5135
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005136#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005137static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5138{
5139 while((uInt & 0xff00000000000000UL) == 0) {
5140 uInt = uInt << 8;
5141 };
5142
5143 UsefulOutBuf UOB;
5144
5145 UsefulOutBuf_Init(&UOB, Buffer);
5146
5147 while(uInt) {
5148 const uint64_t xx = uInt & 0xff00000000000000UL;
5149 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5150 uInt = uInt << 8;
5151 (void)xx;
5152 }
5153
5154 return UsefulOutBuf_OutUBuf(&UOB);
5155}
5156
5157
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005158static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5159 TagSpecification TagSpec,
5160 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005161{
5162 QCBORError uErr;
5163 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005164 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005165 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005166 if(uErr != QCBOR_SUCCESS) {
5167 goto Done;
5168 }
5169
5170 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5171 break; // Successful exit. Moving on to finish decoding.
5172 }
5173
5174 // The item is an array, which means an undecoded
5175 // mantissa and exponent, so decode it. It will then
5176 // have a different type and exit the loop if.
5177 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5178 if(uErr != QCBOR_SUCCESS) {
5179 goto Done;
5180 }
5181
5182 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005183 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005184 }
5185Done:
5186 return uErr;
5187}
5188
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005190static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005191 TagSpecification TagSpec,
5192 QCBORItem *pItem,
5193 int64_t *pnMantissa,
5194 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005195{
5196 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005197
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005198 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005199 if(uErr != QCBOR_SUCCESS) {
5200 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005201 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005202
Laurence Lundblade9b334962020-08-27 10:55:53 -07005203 switch (pItem->uDataType) {
5204
5205 case QCBOR_TYPE_DECIMAL_FRACTION:
5206 case QCBOR_TYPE_BIGFLOAT:
5207 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5208 *pnExponent = pItem->val.expAndMantissa.nExponent;
5209 break;
5210
5211 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5212 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5213 *pnExponent = pItem->val.expAndMantissa.nExponent;
5214 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5215 break;
5216
5217 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5218 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5219 *pnExponent = pItem->val.expAndMantissa.nExponent;
5220 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5221 break;
5222
5223 default:
5224 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5225 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005226
5227 Done:
5228 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005229}
5230
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005231
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005232static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005233 TagSpecification TagSpec,
5234 QCBORItem *pItem,
5235 UsefulBuf BufferForMantissa,
5236 UsefulBufC *pMantissa,
5237 bool *pbIsNegative,
5238 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005239{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005240 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005241
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005242 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005243 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005244 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005245 }
5246
5247 uint64_t uMantissa;
5248
5249 switch (pItem->uDataType) {
5250
5251 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005252 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005253 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5254 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5255 *pbIsNegative = false;
5256 } else {
5257 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5258 *pbIsNegative = true;
5259 }
5260 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5261 *pnExponent = pItem->val.expAndMantissa.nExponent;
5262 break;
5263
5264 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005265 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005266 *pnExponent = pItem->val.expAndMantissa.nExponent;
5267 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5268 *pbIsNegative = false;
5269 break;
5270
5271 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005272 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005273 *pnExponent = pItem->val.expAndMantissa.nExponent;
5274 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5275 *pbIsNegative = true;
5276 break;
5277
5278 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005279 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005280 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005281
5282Done:
5283 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005284}
5285
5286
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005287/*
5288 Public function, see header qcbor/qcbor_decode.h file
5289*/
5290void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5291 uint8_t uTagRequirement,
5292 int64_t *pnMantissa,
5293 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005294{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005295 if(pMe->uLastError != QCBOR_SUCCESS) {
5296 return;
5297 }
5298
5299 QCBORItem Item;
5300 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5301 if(uError) {
5302 pMe->uLastError = (uint8_t)uError;
5303 return;
5304 }
5305
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005306 const TagSpecification TagSpec =
5307 {
5308 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005309 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5310 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5311 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005312 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005313
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005314 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005315}
5316
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317
5318/*
5319 Public function, see header qcbor/qcbor_decode.h file
5320*/
5321void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005322 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005323 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005324 int64_t *pnMantissa,
5325 int64_t *pnExponent)
5326{
5327 if(pMe->uLastError != QCBOR_SUCCESS) {
5328 return;
5329 }
5330
5331 QCBORItem Item;
5332 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5333
5334 const TagSpecification TagSpec =
5335 {
5336 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005337 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5338 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5339 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005340 };
5341
5342 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5343}
5344
5345
5346/*
5347 Public function, see header qcbor/qcbor_decode.h file
5348*/
5349void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005350 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005351 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005352 int64_t *pnMantissa,
5353 int64_t *pnExponent)
5354{
5355 if(pMe->uLastError != QCBOR_SUCCESS) {
5356 return;
5357 }
5358
5359 QCBORItem Item;
5360 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5361
5362 const TagSpecification TagSpec =
5363 {
5364 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005365 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5366 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5367 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005368 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005369
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005370 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5371}
5372
5373
5374/*
5375 Public function, see header qcbor/qcbor_decode.h file
5376*/
5377void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5378 uint8_t uTagRequirement,
5379 UsefulBuf MantissaBuffer,
5380 UsefulBufC *pMantissa,
5381 bool *pbMantissaIsNegative,
5382 int64_t *pnExponent)
5383{
5384 if(pMe->uLastError != QCBOR_SUCCESS) {
5385 return;
5386 }
5387
5388 QCBORItem Item;
5389 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5390 if(uError) {
5391 pMe->uLastError = (uint8_t)uError;
5392 return;
5393 }
5394
5395 const TagSpecification TagSpec =
5396 {
5397 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005398 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5399 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5400 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005401 };
5402
Laurence Lundblade93d89472020-10-03 22:30:50 -07005403 ProcessMantissaAndExponentBig(pMe,
5404 TagSpec,
5405 &Item,
5406 MantissaBuffer,
5407 pMantissa,
5408 pbMantissaIsNegative,
5409 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410}
5411
5412
5413/*
5414 Public function, see header qcbor/qcbor_decode.h file
5415*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005416void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005417 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005418 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005419 UsefulBuf BufferForMantissa,
5420 UsefulBufC *pMantissa,
5421 bool *pbIsNegative,
5422 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005423{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005424 if(pMe->uLastError != QCBOR_SUCCESS) {
5425 return;
5426 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005427
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005428 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005429 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005430 if(pMe->uLastError != QCBOR_SUCCESS) {
5431 return;
5432 }
5433
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005434 const TagSpecification TagSpec =
5435 {
5436 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005437 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5438 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5439 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005440 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005441
Laurence Lundblade93d89472020-10-03 22:30:50 -07005442 ProcessMantissaAndExponentBig(pMe,
5443 TagSpec,
5444 &Item,
5445 BufferForMantissa,
5446 pMantissa,
5447 pbIsNegative,
5448 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005449}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005450
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005451
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005452/*
5453 Public function, see header qcbor/qcbor_decode.h file
5454*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005455void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005456 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005457 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005458 UsefulBuf BufferForMantissa,
5459 UsefulBufC *pMantissa,
5460 bool *pbIsNegative,
5461 int64_t *pnExponent)
5462{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005463 if(pMe->uLastError != QCBOR_SUCCESS) {
5464 return;
5465 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005466
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005467 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005468 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5469 if(pMe->uLastError != QCBOR_SUCCESS) {
5470 return;
5471 }
5472
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005473 const TagSpecification TagSpec =
5474 {
5475 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005476 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5477 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5478 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005479 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005480
5481 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5482}
5483
5484
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005485/*
5486 Public function, see header qcbor/qcbor_decode.h file
5487*/
5488void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5489 uint8_t uTagRequirement,
5490 int64_t *pnMantissa,
5491 int64_t *pnExponent)
5492{
5493 if(pMe->uLastError != QCBOR_SUCCESS) {
5494 return;
5495 }
5496
5497 QCBORItem Item;
5498 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5499 if(uError) {
5500 pMe->uLastError = (uint8_t)uError;
5501 return;
5502 }
5503 const TagSpecification TagSpec =
5504 {
5505 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005506 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5507 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5508 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005509 };
5510
5511 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5512}
5513
5514
5515/*
5516 Public function, see header qcbor/qcbor_decode.h file
5517*/
5518void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005519 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005520 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005521 int64_t *pnMantissa,
5522 int64_t *pnExponent)
5523{
5524 if(pMe->uLastError != QCBOR_SUCCESS) {
5525 return;
5526 }
5527
5528 QCBORItem Item;
5529 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5530 if(pMe->uLastError != QCBOR_SUCCESS) {
5531 return;
5532 }
5533
5534 const TagSpecification TagSpec =
5535 {
5536 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005537 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5538 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5539 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005540 };
5541
5542 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5543}
5544
5545
5546/*
5547 Public function, see header qcbor/qcbor_decode.h file
5548*/
5549void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005550 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005551 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005552 int64_t *pnMantissa,
5553 int64_t *pnExponent)
5554{
5555 if(pMe->uLastError != QCBOR_SUCCESS) {
5556 return;
5557 }
5558
5559 QCBORItem Item;
5560 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5561 if(pMe->uLastError != QCBOR_SUCCESS) {
5562 return;
5563 }
5564
5565 const TagSpecification TagSpec =
5566 {
5567 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005568 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5569 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5570 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005571 };
5572
5573 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5574}
5575
5576
5577/*
5578 Public function, see header qcbor/qcbor_decode.h file
5579*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005580void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5581 uint8_t uTagRequirement,
5582 UsefulBuf MantissaBuffer,
5583 UsefulBufC *pMantissa,
5584 bool *pbMantissaIsNegative,
5585 int64_t *pnExponent)
5586{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005587 if(pMe->uLastError != QCBOR_SUCCESS) {
5588 return;
5589 }
5590
5591 QCBORItem Item;
5592 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5593 if(uError) {
5594 pMe->uLastError = (uint8_t)uError;
5595 return;
5596 }
5597
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005598 const TagSpecification TagSpec =
5599 {
5600 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005601 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5602 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5603 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005604 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005605
5606 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005607}
5608
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005609
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005610/*
5611 Public function, see header qcbor/qcbor_decode.h file
5612*/
5613void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005614 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005615 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005616 UsefulBuf BufferForMantissa,
5617 UsefulBufC *pMantissa,
5618 bool *pbIsNegative,
5619 int64_t *pnExponent)
5620{
5621 if(pMe->uLastError != QCBOR_SUCCESS) {
5622 return;
5623 }
5624
5625 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005626 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5627 if(pMe->uLastError != QCBOR_SUCCESS) {
5628 return;
5629 }
5630
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005631 const TagSpecification TagSpec =
5632 {
5633 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005634 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5635 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5636 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005637 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005638
Laurence Lundblade93d89472020-10-03 22:30:50 -07005639 ProcessMantissaAndExponentBig(pMe,
5640 TagSpec,
5641 &Item,
5642 BufferForMantissa,
5643 pMantissa,
5644 pbIsNegative,
5645 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005646}
5647
5648
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005649/*
5650 Public function, see header qcbor/qcbor_decode.h file
5651*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005652void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005653 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005654 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005655 UsefulBuf BufferForMantissa,
5656 UsefulBufC *pMantissa,
5657 bool *pbIsNegative,
5658 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005659{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005660 if(pMe->uLastError != QCBOR_SUCCESS) {
5661 return;
5662 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005663
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005664 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005665 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5666 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005667 return;
5668 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005669
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005670 const TagSpecification TagSpec =
5671 {
5672 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005673 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5674 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5675 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005676 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005677
Laurence Lundblade93d89472020-10-03 22:30:50 -07005678 ProcessMantissaAndExponentBig(pMe,
5679 TagSpec,
5680 &Item,
5681 BufferForMantissa,
5682 pMantissa,
5683 pbIsNegative,
5684 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005685}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005686
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005687#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */