blob: b46908dae787e0cbd48b566b0ab1cb39f59200e4 [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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -080039
40#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
44
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 Lundblade3f1318a2021-01-04 18:26:44 -080048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800242 /* Works for both definite- and indefinitelength 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 Lundblade3f1318a2021-01-04 18:26:44 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -0800294 /* Only call on a definite-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 Lundblade3f1318a2021-01-04 18:26:44 -0800302 /* Only call on a definite-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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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
343 * 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 Lundblade3f1318a2021-01-04 18:26:44 -0800367 /* Nothing to do for empty definite-length 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 Lundblade3f1318a2021-01-04 18:26:44 -0800371 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundblade3f1318a2021-01-04 18:26:44 -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 Lundbladecf41c522021-02-20 10:19:07 -0700425 uint32_t uEndOffset,
426 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700428 QCBORError uError;
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 Lundblade3f1318a2021-01-04 18:26:44 -0800435 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700436 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
437 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700457 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
458 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
459 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800460}
461
462
463static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700464DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700465{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700466 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700467 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
468 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700469}
470
471
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700472static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800473DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
474 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700475{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700476 *pSave = *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 Lundblade3f1318a2021-01-04 18:26:44 -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_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700490{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700491 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700492}
493
494
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800495
496
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800497#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
500
501 The following four functions are pretty wrappers for invocation of
502 the string allocator supplied by the caller.
503
Laurence Lundbladeee851742020-01-08 08:37:05 -0800504 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800507StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800508{
509 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
510}
511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512// StringAllocator_Reallocate called with pMem NULL is
513// equal to StringAllocator_Allocate()
514static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800515StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516 void *pMem,
517 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800518{
519 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
520}
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800523StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800529StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530{
531 if(pMe->pfAllocator) {
532 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
533 }
534}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800535#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800536
537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800538
539
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540/*===========================================================================
541 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800543 See qcbor/qcbor_decode.h for definition of the object
544 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700546/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800547 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700548 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800549void QCBORDecode_Init(QCBORDecodeContext *pMe,
550 UsefulBufC EncodedCBOR,
551 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800553 memset(pMe, 0, sizeof(QCBORDecodeContext));
554 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
555 /* Don't bother with error check on decode mode. If a bad value is
556 * passed it will just act as if the default normal mode of 0 was set.
557 */
558 pMe->uDecodeMode = (uint8_t)nDecodeMode;
559 DecodeNesting_Init(&(pMe->nesting));
560
561 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
562 * GetNext_TaggedItem() and MapTagNumber(). */
563 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564}
565
566
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800567#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
568
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700569/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800570 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700571 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800572void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
573 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800574 void *pAllocateContext,
575 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700576{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800577 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
578 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
579 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800581#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700582
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800584
585
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800586/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800587 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800588 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800589void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700591{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800592 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700593 (void)pMe;
594 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700595}
596
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700597
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800598
599
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700600/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800601 * Decoding items is done in six layers, one calling the next one
602 * down. If a layer has no work to do for a particular item, it
603 * returns quickly.
604 *
605 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
606 * data items, turning them into the local C representation. For the
607 * most simple it is just associating a QCBOR_TYPE with the data. For
608 * the complex ones that an aggregate of data items, there is some
609 * further decoding and some limited recursion.
610 *
611 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
612 * ends of maps and arrays. It tracks descending into and ascending
613 * out of maps/arrays. It processes breaks that terminate
614 * indefinite-length maps and arrays.
615 *
616 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
617 * items, the label and the data, that make up a map entry. It only
618 * does work on maps. It combines the label and data items into one
619 * labeled item.
620 *
621 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
622 * numbers. It turns the tag numbers into bit flags associated with
623 * the data item. No actual decoding of the contents of the tag is
624 * performed here.
625 *
626 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
627 * that make up an indefinite-length string into one string item. It
628 * uses the string allocator to create contiguous space for the
629 * item. It processes all breaks that are part of indefinite-length
630 * strings.
631 *
632 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
633 * CBOR. Each atomic data item has a "major type", an integer
634 * "argument" and optionally some content. For text and byte strings,
635 * the content is the bytes that make up the string. These are the
636 * smallest data items that are considered to be well-formed. The
637 * content may also be other data items in the case of aggregate
638 * types. They are not handled in this layer.
639 *
640 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
641 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800643
644
645/*
646 * Note about use of int and unsigned variables.
647 *
648 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
649 * used carefully here, and in particular why it isn't used in the
650 * public interface. Also see
651 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
652 *
653 * Int is used for values that need less than 16-bits and would be
654 * subject to integer promotion and result in complaining from static
655 * analyzers.
656 */
657
658
659/**
660 * @brief Decode the CBOR head, the type and argument.
661 *
662 * @param[in] pUInBuf The input buffer to read from.
663 * @param[out] pnMajorType The decoded major type.
664 * @param[out] puArgument The decoded argument.
665 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
666 *
667 * @retval QCBOR_ERR_UNSUPPORTED
668 * @retval QCBOR_ERR_HIT_END
669 *
670 * This decodes the CBOR "head" that every CBOR data item has. See
671 * longer explaination of the head in documentation for
672 * QCBOREncode_EncodeHead().
673 *
674 * This does the network->host byte order conversion. The conversion
675 * here also results in the conversion for floats in addition to that
676 * for lengths, tags and integer values.
677 *
678 * The int type is preferred to uint8_t for some variables as this
679 * avoids integer promotions, can reduce code size and makes static
680 * analyzers happier.
681 */
682static inline QCBORError
683DecodeHead(UsefulInputBuf *pUInBuf,
684 int *pnMajorType,
685 uint64_t *puArgument,
686 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800688 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800689
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800690 /* Get the initial byte that every CBOR data item has and break it
691 * down. */
692 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 const int nTmpMajorType = nInitialByte >> 5;
694 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800695
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800696 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800697 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800698
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800700 /* Need to get 1,2,4 or 8 additional argument bytes. Map
701 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
702 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800703 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800705 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800706 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800707 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800708 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800709 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
710 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800712 /* The reserved and thus-far unused additional info values */
713 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800714 goto Done;
715 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800716 /* Less than 24, additional info is argument or 31, an
717 * indefinite-length. No more bytes to get.
718 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800719 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800723 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 goto Done;
725 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800726
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 /* All successful if arrived here. */
728 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800730 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800731 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800732
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800734 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735}
736
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800737
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800738/**
739 * @brief Decode integer types, major types 0 and 1.
740 *
741 * @param[in] nMajorType The CBOR major type (0 or 1).
742 * @param[in] uArgument The argument from the head.
743 * @param[out] pDecodedItem The filled in decoded item.
744 *
745 * @retval QCBOR_ERR_INT_OVERFLOW
746 *
747 * Must only be called when major type is 0 or 1.
748 *
749 * CBOR doesn't explicitly specify two's compliment for integers but
750 * all CPUs use it these days and the test vectors in the RFC are
751 * so. All integers in the CBOR structure are positive and the major
752 * type indicates positive or negative. CBOR can express positive
753 * integers up to 2^x - 1 where x is the number of bits and negative
754 * integers down to 2^x. Note that negative numbers can be one more
755 * away from zero than positive. Stdint, as far as I can tell, uses
756 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700758static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800759DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800761 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800762
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800764 if (uArgument <= INT64_MAX) {
765 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700766 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800769 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800774 if(uArgument <= INT64_MAX) {
775 /* CBOR's representation of negative numbers lines up with
776 * the two-compliment representation. A negative integer has
777 * one more in range than a positive integer. INT64_MIN is
778 * equal to (-INT64_MAX) - 1.
779 */
780 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800784 /* C can't represent a negative integer in this range so it
785 * is an error.
786 */
787 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 }
789 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792}
793
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800794
795/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
797#error QCBOR_TYPE_FALSE macro value wrong
798#endif
799
800#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
801#error QCBOR_TYPE_TRUE macro value wrong
802#endif
803
804#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
805#error QCBOR_TYPE_NULL macro value wrong
806#endif
807
808#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
809#error QCBOR_TYPE_UNDEF macro value wrong
810#endif
811
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700812#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
813#error QCBOR_TYPE_BREAK macro value wrong
814#endif
815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
817#error QCBOR_TYPE_DOUBLE macro value wrong
818#endif
819
820#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
821#error QCBOR_TYPE_FLOAT macro value wrong
822#endif
823
Laurence Lundblade9b334962020-08-27 10:55:53 -0700824
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800825/**
826 * @brief Decode major type 7 -- true, false, floating-point, break...
827 *
828 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
829 * @param[in] uArgument The argument from the head.
830 * @param[out] pDecodedItem The filled in decoded item.
831 *
832 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
833 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800836static inline QCBORError
837DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
838{
839 QCBORError uReturn = QCBOR_SUCCESS;
840
841 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
842 * checks above make sure uAdditionalInfo values line up with
843 * uDataType values. DecodeHead() never returns an AdditionalInfo
844 * > 0x1f so cast is safe.
845 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800849 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
850 * are caught before this is called.
851 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800853 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700854#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800855 /* Half-precision is returned as a double. The cast to
856 * uint16_t is safe because the encoded value was 16 bits. It
857 * was widened to 64 bits to be passed in here.
858 */
859 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700860 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800861#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800862 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700864 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800865 case SINGLE_PREC_FLOAT: /* 26 */
866 /* Single precision is normally returned as a double since
867 * double is widely supported, there is no loss of precision,
868 * it makes it easy for the caller in most cases and it can
869 * be converted back to single with no loss of precision
870 *
871 * The cast to uint32_t is safe because the encoded value was
872 * 32 bits. It was widened to 64 bits to be passed in here.
873 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700874 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800875 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 /* In the normal case, use HW to convert float to
878 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700879 pDecodedItem->val.dfnum = (double)f;
880 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800881#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800882 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 pDecodedItem->val.fnum = f;
884 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
885
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800886 /* IEEE754_FloatToDouble() could be used here to return as
887 * a double, but it adds object code and most likely
888 * anyone disabling FLOAT HW use doesn't care about floats
889 * and wants to save object code.
890 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800891#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700892 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700893 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895 case DOUBLE_PREC_FLOAT: /* 27 */
896 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700897 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700898 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800900 case CBOR_SIMPLEV_FALSE: /* 20 */
901 case CBOR_SIMPLEV_TRUE: /* 21 */
902 case CBOR_SIMPLEV_NULL: /* 22 */
903 case CBOR_SIMPLEV_UNDEF: /* 23 */
904 case CBOR_SIMPLE_BREAK: /* 31 */
905 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800907 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
908 if(uArgument <= CBOR_SIMPLE_BREAK) {
909 /* This takes out f8 00 ... f8 1f which should be encoded
910 * as e0 … f7
911 */
912 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700913 goto Done;
914 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800915 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800917 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800919 /* DecodeHead() will make uArgument equal to
920 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
921 * safe because the 2, 4 and 8 byte lengths of uNumber are in
922 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800924 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 break;
926 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700928Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800929 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930}
931
932
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800933/**
934 * @brief Decode text and byte strings
935 *
936 * @param[in] pAllocator The string allocator or NULL.
937 * @param[in] uStrLen The length of the string.
938 * @param[in] pUInBuf The surce from which to read the string's bytes.
939 * @param[out] pDecodedItem The filled in decoded item.
940 *
941 * @retval QCBOR_ERR_HIT_END
942 * @retval QCBOR_ERR_STRING_ALLOCATE
943 * @retval QCBOR_ERR_STRING_TOO_LONG
944 *
945 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
946 * pDecodedItem. If @c pAllocator is not NULL then memory for the
947 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800949static inline QCBORError
950DecodeBytes(const QCBORInternalAllocator *pAllocator,
951 uint64_t uStrLen,
952 UsefulInputBuf *pUInBuf,
953 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800955 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800957 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
958 * CPUs. This check makes the casts to size_t below safe.
959 *
960 * The max is 4 bytes less than the largest sizeof() so this can be
961 * tested by putting a SIZE_MAX length in the CBOR test input (no
962 * one will care the limit on strings is 4 bytes shorter).
963 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800965 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 goto Done;
967 }
968
969 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530970 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800971 /* Failed to get the bytes for this string item */
972 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530973 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530975
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800976#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800977 /* Note that this is not where allocation to coalesce
978 * indefinite-length strings is done. This is for when the caller
979 * has requested all strings be allocated. Disabling indefinite
980 * length strings also disables this allocate-all option.
981 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800982 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530985 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800986 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530987 goto Done;
988 }
989 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800990 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800991 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800993#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
994 (void)pAllocator;
995#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
996
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800997 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800998 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301000Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001001 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002}
1003
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001004
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005/**
1006 * @brief Map the CBOR major types for strings to the QCBOR types.
1007 *
1008 * @param[in] nCBORMajorType The CBOR major type to convert.
1009 * @retturns QCBOR type number.
1010 *
1011 * This only works for the two string types.
1012 */
1013static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001014{
1015 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1016 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1017 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001019 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1020 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1021 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001022
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 return (uint8_t)(nCBORMajorType + 4);
1024}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025
1026
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001027/**
1028 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1029 *
1030 * @param[in] nCBORMajorType The CBOR major type to convert.
1031 * @retturns QCBOR type number.
1032 *
1033 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001034 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001035static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001037 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1038 #error QCBOR_TYPE_ARRAY value not lined up with major type
1039 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001041 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1042 #error QCBOR_TYPE_MAP value not lined up with major type
1043 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001045 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046}
1047
1048
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001049/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001050 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001052 * @param[in] pUInBuf Input buffer to read data item from.
1053 * @param[out] pDecodedItem The filled-in decoded item.
1054 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001055 *
1056 * @retval QCBOR_ERR_UNSUPPORTED
1057 * @retval QCBOR_ERR_HIT_END
1058 * @retval QCBOR_ERR_INT_OVERFLOW
1059 * @retval QCBOR_ERR_STRING_ALLOCATE
1060 * @retval QCBOR_ERR_STRING_TOO_LONG
1061 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1062 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001063 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1064 *
1065 * This decodes the most primitive / atomic data item. It does
1066 * no combing of data items.
1067 */
1068static QCBORError
1069DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1070 QCBORItem *pDecodedItem,
1071 const QCBORInternalAllocator *pAllocator)
1072{
1073 QCBORError uReturn;
1074
1075 /* Get the major type and the argument. The argument could be
1076 * length of more bytes or the value depending on the major
1077 * type. nAdditionalInfo is an encoding of the length of the
1078 * uNumber and is needed to decode floats and doubles.
1079 */
1080 int nMajorType = 0;
1081 uint64_t uArgument = 0;
1082 int nAdditionalInfo = 0;
1083
1084 memset(pDecodedItem, 0, sizeof(QCBORItem));
1085
1086 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1087 if(uReturn) {
1088 goto Done;
1089 }
1090
1091 /* At this point the major type and the argument are valid. We've
1092 * got the type and the argument that starts every CBOR data item.
1093 */
1094 switch (nMajorType) {
1095 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1096 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1097 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1098 uReturn = QCBOR_ERR_BAD_INT;
1099 } else {
1100 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1101 }
1102 break;
1103
1104 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1105 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1106 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1107 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1108 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1109 } else {
1110 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1111 }
1112 break;
1113
1114 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1115 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1116 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1117 /* Indefinite-length string. */
1118#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1119 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1120#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1121 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1122 break;
1123#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1124 } else {
1125 /* Definite-length string. */
1126 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1127 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1128 goto Done;
1129 }
1130 /* cast OK because of check above */
1131 pDecodedItem->val.uCount = (uint16_t)uArgument;
1132 }
1133 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1134 break;
1135
1136 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1137 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1138 uReturn = QCBOR_ERR_BAD_INT;
1139 } else {
1140 pDecodedItem->val.uTagV = uArgument;
1141 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1142 }
1143 break;
1144
1145 case CBOR_MAJOR_TYPE_SIMPLE:
1146 /* Major type 7: float, double, true, false, null... */
1147 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1148 break;
1149
1150 default:
1151 /* Never happens because DecodeHead() should never return > 7 */
1152 uReturn = QCBOR_ERR_UNSUPPORTED;
1153 break;
1154 }
1155
1156Done:
1157 return uReturn;
1158}
1159
1160
1161/**
1162 * @brief Process indefinite-length strings (decode layer 5).
1163 *
1164 * @param[in] pMe Decoder context
1165 * @param[out] pDecodedItem The decoded item that work is done on.
1166 *
1167 * @retval QCBOR_ERR_UNSUPPORTED
1168 * @retval QCBOR_ERR_HIT_END
1169 * @retval QCBOR_ERR_INT_OVERFLOW
1170 * @retval QCBOR_ERR_STRING_ALLOCATE
1171 * @retval QCBOR_ERR_STRING_TOO_LONG
1172 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1173 * @retval QCBOR_ERR_BAD_TYPE_7
1174 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001175 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1176 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001177 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001178 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001179 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001180 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001181 * If it is, this loops getting the subsequent chunk data items that
1182 * make up the string. The string allocator is used to make a
1183 * contiguous buffer for the chunks. When this completes @c
1184 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001185 *
1186 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001187 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001188static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001189QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001190{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001191 /* Aproximate stack usage
1192 * 64-bit 32-bit
1193 * local vars 32 16
1194 * 2 UsefulBufs 32 16
1195 * QCBORItem 56 52
1196 * TOTAL 120 74
1197 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001198
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001199 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001200 * coalescing the chunks of an indefinite-length string, 2)
1201 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001202 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001203 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204 * strings cannot be processed at all without a string allocator.
1205 *
1206 * The second used is in DecodeBytes() which is called by
1207 * GetNext_Item() below. This second use unneccessary for most use
1208 * and only happens when requested in the call to
1209 * QCBORDecode_SetMemPool(). If the second use not requested then
1210 * NULL is passed for the string allocator to GetNext_Item().
1211 *
1212 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1213 * allocator altogether and thus both of these uses. It reduced the
1214 * decoder object code by about 400 bytes.
1215 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001216 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001217
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001218#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001219 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001220
1221 if(pMe->StringAllocator.pfAllocator) {
1222 pAllocator = &(pMe->StringAllocator);
1223 if(pMe->bStringAllocateAll) {
1224 pAllocatorForGetNext = pAllocator;
1225 }
1226 }
1227#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1228
1229 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001230 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001231 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001232 goto Done;
1233 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001234
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001235 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001236 const uint8_t uStringType = pDecodedItem->uDataType;
1237 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001238 goto Done;
1239 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001240
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001241 /* Is this a string with an indefinite length? */
1242 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1243 goto Done;
1244 }
1245
1246#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001247 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001248 if(pAllocator == NULL) {
1249 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1250 goto Done;
1251 }
1252
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001253 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001254 UsefulBufC FullString = NULLUsefulBufC;
1255
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001256 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001257 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001258 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001259 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001260 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001261 * be allocated. They are always copied in the the contiguous
1262 * buffer allocated here.
1263 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001264 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001265 if(uReturn) {
1266 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001267 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001268
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001269 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001270 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001271 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001272 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301273 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274 break;
1275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001276
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001277 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001278 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001280 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001281 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001282 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001283 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1284 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285 break;
1286 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001287
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001288 /* The first time throurgh FullString.ptr is NULL and this is
1289 * equivalent to StringAllocator_Allocate(). Subsequently it is
1290 * not NULL and a reallocation happens.
1291 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001292 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1293 UNCONST_POINTER(FullString.ptr),
1294 FullString.len + StringChunkItem.val.string.len);
1295
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001296 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001298 break;
1299 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001300
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001301 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001302 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001305 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1306 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001307 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001308 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001309#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1310 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1311#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001312
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001313Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001314 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001315}
1316
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001317
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001318/**
1319 * @brief This converts a tag number to a shorter mapped value for storage.
1320 *
1321 * @param[in] pMe The decode context.
1322 * @param[in] uUnMappedTag The tag number to map
1323 * @param[out] puMappedTagNumer The stored tag number.
1324 *
1325 * @return error code.
1326 *
1327 * The main point of mapping tag numbers is make QCBORItem
1328 * smaller. With this mapping storage of 4 tags takes up 8
1329 * bytes. Without, it would take up 32 bytes.
1330 *
1331 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1332 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1333 *
1334 * See also UnMapTagNumber() and @ref QCBORItem.
1335 */
1336static inline QCBORError
1337MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1338{
1339 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1340 unsigned uTagMapIndex;
1341 /* Is there room in the tag map, or is it in it already? */
1342 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1343 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1344 break;
1345 }
1346 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1347 break;
1348 }
1349 }
1350 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1351 return QCBOR_ERR_TOO_MANY_TAGS;
1352 }
1353
1354 /* Covers the cases where tag is new and were it is already in the map */
1355 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1356 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1357
1358 } else {
1359 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1360 }
1361
1362 return QCBOR_SUCCESS;
1363}
1364
1365
1366/**
1367 * @brief This converts a mapped tag number to the actual tag number.
1368 *
1369 * @param[in] pMe The decode context.
1370 * @param[in] uMappedTagNumber The stored tag number.
1371 *
1372 * @return The actual tag number is returned or
1373 * @ref CBOR_TAG_INVALID64 on error.
1374 *
1375 * This is the reverse of MapTagNumber()
1376 */
1377static uint64_t
1378UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1379{
1380 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1381 return uMappedTagNumber;
1382 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001383 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001384 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001385 /* This won't be negative because of code below in
1386 * MapTagNumber()
1387 */
1388 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1389 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001390 }
1391}
1392
Laurence Lundblade9b334962020-08-27 10:55:53 -07001393
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001394/**
1395 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1396 *
1397 * @param[in] pMe Decoder context
1398 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001399
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001400 * @retval QCBOR_ERR_UNSUPPORTED
1401 * @retval QCBOR_ERR_HIT_END
1402 * @retval QCBOR_ERR_INT_OVERFLOW
1403 * @retval QCBOR_ERR_STRING_ALLOCATE
1404 * @retval QCBOR_ERR_STRING_TOO_LONG
1405 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1406 * @retval QCBOR_ERR_BAD_TYPE_7
1407 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1408 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1409 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1410 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1411 * @retval QCBOR_ERR_TOO_MANY_TAGS
1412 *
1413 * This loops getting atomic data items until one is not a tag
1414 * number. Usually this is largely pass-through because most
1415 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001416 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001417static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001418QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001419{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001420 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1421
1422 /* Initialize to CBOR_TAG_INVALID16 */
1423 #if CBOR_TAG_INVALID16 != 0xffff
1424 /* Be sure the memset does the right thing. */
1425 #err CBOR_TAG_INVALID16 tag not defined as expected
1426 #endif
1427 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001428
Laurence Lundblade9b334962020-08-27 10:55:53 -07001429 QCBORError uReturn = QCBOR_SUCCESS;
1430
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001431 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001432 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001433 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001434 if(uErr != QCBOR_SUCCESS) {
1435 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001436 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001437 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001438
Laurence Lundblade9b334962020-08-27 10:55:53 -07001439 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001440 /* Successful exit from loop; maybe got some tags, maybe not */
1441 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001442 break;
1443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001444
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001445 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1446 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001447 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001448 /* Continue on to get all tags wrapping this item even though
1449 * it is erroring out in the end. This allows decoding to
1450 * continue. This is a resource limit error, not a problem
1451 * with being well-formed CBOR.
1452 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001453 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001454 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 /* Slide tags over one in the array to make room at index 0.
1456 * Must use memmove because the move source and destination
1457 * overlap.
1458 */
1459 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001460
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001461 /* Map the tag */
1462 uint16_t uMappedTagNumer;
1463 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1464 /* Continue even on error so as to consume all tags wrapping
1465 * this data item so decoding can go on. If MapTagNumber()
1466 * errors once it will continue to error.
1467 */
1468 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001469 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001470
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001471Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001472 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001473}
1474
1475
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001476/**
1477 * @brief Combine a map entry label and value into one item (decode layer 3).
1478 *
1479 * @param[in] pMe Decoder context
1480 * @param[out] pDecodedItem The decoded item that work is done on.
1481 *
1482 * @retval QCBOR_ERR_UNSUPPORTED
1483 * @retval QCBOR_ERR_HIT_END
1484 * @retval QCBOR_ERR_INT_OVERFLOW
1485 * @retval QCBOR_ERR_STRING_ALLOCATE
1486 * @retval QCBOR_ERR_STRING_TOO_LONG
1487 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1488 * @retval QCBOR_ERR_BAD_TYPE_7
1489 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1490 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1491 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1492 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1493 * @retval QCBOR_ERR_TOO_MANY_TAGS
1494 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1495 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1496 *
1497 * If a the current nesting level is a map, then this
1498 * combines pairs of items into one data item with a label
1499 * and value.
1500 *
1501 * This is pass-through if the current nesting leve is
1502 * not a map.
1503 *
1504 * This also implements maps-as-array mode where a map
1505 * is treated like an array to allow caller to do their
1506 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001507 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001508static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001509QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001510{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001511 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1512 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001513 goto Done;
1514 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001515
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001516 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1517 /* Break can't be a map entry */
1518 goto Done;
1519 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001520
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001521 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1522 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001523
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001524 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1525 /* Save label in pDecodedItem and get the next which will
1526 * be the real data item.
1527 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001528 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001529 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1530 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001531 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001532 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001533
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301534 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001535
1536 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001537 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001538 pDecodedItem->label.string = LabelItem.val.string;
1539 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001540 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1541 /* It's not a string and we only want strings */
1542 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001543 goto Done;
1544 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1545 pDecodedItem->label.int64 = LabelItem.val.int64;
1546 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1547 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1548 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1549 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1550 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1551 pDecodedItem->label.string = LabelItem.val.string;
1552 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1553 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1554 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001555 /* label is not an int or a string. It is an arrray
1556 * or a float or such and this implementation doesn't handle that.
1557 * Also, tags on labels are ignored.
1558 */
1559 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001560 goto Done;
1561 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001562 }
1563 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 /* Decoding of maps as arrays to let the caller decide what to do
1565 * about labels, particularly lables that are not integers or
1566 * strings.
1567 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001568 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001569 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001570 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001571 goto Done;
1572 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001573 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001574 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1575 * Cast is needed because of integer promotion.
1576 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001577 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001578 }
1579 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001580
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001581Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001582 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001583}
1584
1585
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001586#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001587/**
1588 * @brief Peek and see if next data item is a break;
1589 *
1590 * @param[in] pUIB UsefulInputBuf to read from.
1591 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1592 *
1593 * @return Any decoding error.
1594 *
1595 * See if next item is a CBOR break. If it is, it is consumed,
1596 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001597*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001598static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001599NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1600{
1601 *pbNextIsBreak = false;
1602 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001603 QCBORItem Peek;
1604 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001605 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001606 if(uReturn != QCBOR_SUCCESS) {
1607 return uReturn;
1608 }
1609 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001610 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001611 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001612 } else {
1613 *pbNextIsBreak = true;
1614 }
1615 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001616
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001617 return QCBOR_SUCCESS;
1618}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001619#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001620
1621
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001622/**
1623 * @brief Ascend up nesting levels if all items in them have been consumed.
1624 *
1625 * @param[in] pMe The decode context.
1626 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1627 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001628 * An item was just consumed, now figure out if it was the
1629 * end of an array/map map that can be closed out. That
1630 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001631*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001632static QCBORError
1633QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001634{
1635 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001636
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001637 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001638 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1639
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001640 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1641 /* Nesting level is bstr-wrapped CBOR */
1642
1643 /* Ascent for bstr-wrapped CBOR is always by explicit call
1644 * so no further ascending can happen.
1645 */
1646 break;
1647
1648 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1649 /* Level is a definite-length array/map */
1650
1651 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001652 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1653 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001654 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001655 break;
1656 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001657 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001658 * is time to ascend one level. This happens below.
1659 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001660
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001661#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001662 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001663 /* Level is an indefinite-length array/map. */
1664
1665 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001666 bool bIsBreak = false;
1667 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1668 if(uReturn != QCBOR_SUCCESS) {
1669 goto Done;
1670 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001671
1672 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001673 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001674 break;
1675 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001676
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001677 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001678 * it is time to ascend one level.
1679 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001680
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001681#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001682 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001683
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001684
1685 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001686
Laurence Lundblade93d89472020-10-03 22:30:50 -07001687 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688 * QCBORDecode_ExitBoundedMode().
1689 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001690 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001691 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001692 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001693 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001694 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001695 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001696
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001697 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001698 break;
1699 }
1700
1701 /* Finally, actually ascend one level. */
1702 DecodeNesting_Ascend(&(pMe->nesting));
1703 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001704
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001705 uReturn = QCBOR_SUCCESS;
1706
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001707#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001708Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001709#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1710
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001711 return uReturn;
1712}
1713
1714
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001715/**
1716 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1717 *
1718 * @param[in] pMe Decoder context
1719 * @param[out] pDecodedItem The decoded item that work is done on.
1720 *
1721 * @retval QCBOR_ERR_UNSUPPORTED
1722 * @retval QCBOR_ERR_HIT_END
1723 * @retval QCBOR_ERR_INT_OVERFLOW
1724 * @retval QCBOR_ERR_STRING_ALLOCATE
1725 * @retval QCBOR_ERR_STRING_TOO_LONG
1726 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1727 * @retval QCBOR_ERR_BAD_TYPE_7
1728 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1729 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1730 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1731 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1732 * @retval QCBOR_ERR_TOO_MANY_TAGS
1733 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1734 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1735 * @retval QCBOR_ERR_NO_MORE_ITEMS
1736 * @retval QCBOR_ERR_BAD_BREAK
1737 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1738 *
1739 * This handles the traversal descending into and asecnding out of
1740 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1741 * definite- and indefinte-length maps and arrays by looking at the
1742 * item count or finding CBOR breaks. It detects the ends of the
1743 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001744 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001745static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001746QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001747{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001748 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001749 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001750
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001751 /* If out of bytes to consume, it is either the end of the
1752 * top-level sequence of some bstr-wrapped CBOR that was entered.
1753 *
1754 * In the case of bstr-wrapped CBOR, the length of the
1755 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1756 * the bstr-wrapped CBOR is exited, the length is set back to the
1757 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001758 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001759 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001760 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001761 goto Done;
1762 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001763
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001764 /* Check to see if at the end of a bounded definite-length map or
1765 * array. The check for a break ending indefinite-length array is
1766 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001767 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001768 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001769 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001770 goto Done;
1771 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001772
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001773 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001774 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001775 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1776 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001777 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001778 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301779
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001780 /* Breaks ending arrays/maps are processed later in the call to
1781 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001782 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301783 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001784 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301785 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301786 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001787
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001788 /* Record the nesting level for this data item before processing
1789 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001790 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001791 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001792
Laurence Lundblade642282a2020-06-23 12:00:33 -07001793
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001794 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001795 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001796 /* If the new item is a map or array, descend.
1797 *
1798 * Empty indefinite-length maps and arrays are descended into,
1799 * but then ascended out of in the next chunk of code.
1800 *
1801 * Maps and arrays do count as items in the map/array that
1802 * encloses them so a decrement needs to be done for them too,
1803 * but that is done only when all the items in them have been
1804 * processed, not when they are opened with the exception of an
1805 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001806 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001807 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001808 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001809 pDecodedItem->uDataType,
1810 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001811 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001812 /* This error is probably a traversal error and it overrides
1813 * the non-traversal error.
1814 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001815 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001816 goto Done;
1817 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001818 }
1819
Laurence Lundblade02625d42020-06-25 14:41:41 -07001820 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1821 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1822 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001823 /* The following cases are handled here:
1824 * - A non-aggregate item like an integer or string
1825 * - An empty definite-length map or array
1826 * - An indefinite-length map or array that might be empty or might not.
1827 *
1828 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1829 * for an definite-length map/array and break detection for an
1830 * indefinite-0length map/array. If the end of the map/array was
1831 * reached, then it ascends nesting levels, possibly all the way
1832 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001833 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001834 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001835 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001836 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001837 /* This error is probably a traversal error and it overrides
1838 * the non-traversal error.
1839 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001840 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001841 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001842 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301843 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001844
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001845 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001846 /* Tell the caller what level is next. This tells them what
1847 * maps/arrays were closed out and makes it possible for them to
1848 * reconstruct the tree with just the information returned in a
1849 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001850 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001851 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001852 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001853 pDecodedItem->uNextNestLevel = 0;
1854 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001855 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001856 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001857
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001858Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001859 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001860}
1861
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001862
1863/**
1864 * @brief Shift 0th tag out of the tag list.
1865 *
1866 * pDecodedItem[in,out] The data item to convert.
1867 *
1868 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1869 * shifted into empty slot at the end of the tag list.
1870 */
1871static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001872{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001873 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1874 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1875 }
1876 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001877}
1878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001879
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001880/**
1881 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1882 *
1883 * pDecodedItem[in,out] The data item to convert.
1884 *
1885 * @retval QCBOR_ERR_DATE_OVERFLOW
1886 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1887 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1888 *
1889 * The epoch date tag defined in QCBOR allows for floating-point
1890 * dates. It even allows a protocol to flop between date formats when
1891 * ever it wants. Floating-point dates aren't that useful as they are
1892 * only needed for dates beyond the age of the earth.
1893 *
1894 * This converts all the date formats into one format of an unsigned
1895 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001896 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001897static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001898{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001899 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001900
1901 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1902
1903 switch (pDecodedItem->uDataType) {
1904
1905 case QCBOR_TYPE_INT64:
1906 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1907 break;
1908
1909 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001910 /* This only happens for CBOR type 0 > INT64_MAX so it is
1911 * always an overflow.
1912 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001913 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1914 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001915 break;
1916
1917 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001918 case QCBOR_TYPE_FLOAT:
1919#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001920 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001921 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001922 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001923 pDecodedItem->val.dfnum :
1924 (double)pDecodedItem->val.fnum;
1925
1926 /* The conversion from float to integer requires overflow
1927 * detection since floats can be much larger than integers.
1928 * This implementation errors out on these large float values
1929 * since they are beyond the age of the earth.
1930 *
1931 * These constants for the overflow check are computed by the
1932 * compiler. They are not computed at run time.
1933 *
1934 * The factor of 0x7ff is added/subtracted to avoid a
1935 * rounding error in the wrong direction when the compiler
1936 * computes these constants. There is rounding because an
1937 * 64-bit integer has 63 bits of precision where a double
1938 * only has 53 bits. Without the 0x7ff factor, the compiler
1939 * may round up and produce a double for the bounds check
1940 * that is larger than can be stored in a 64-bit integer. The
1941 * amount of 0x7ff is picked because it has 11 bits set.
1942 *
1943 * Without the 0x7ff there is a ~30 minute range of time
1944 * values 10 billion years in the past and in the future
1945 * where this code could go wrong. Some compilers correctly
1946 * generate a warning or error without the 0x7ff.
1947 */
1948 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1949 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1950
1951 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001952 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001953 goto Done;
1954 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001955
1956 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001958 pDecodedItem->val.epochDate.fSecondsFraction =
1959 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001961#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001962
Laurence Lundbladec7114722020-08-13 05:11:40 -07001963 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001964 goto Done;
1965
Laurence Lundblade9682a532020-06-06 18:33:04 -07001966#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001967 break;
1968
1969 default:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001970 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001971 goto Done;
1972 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001973
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1975
1976Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001977 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001978}
1979
1980
1981#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001982/**
1983 * @brief Decode decimal fractions and big floats.
1984 *
1985 * @param[in] pMe The decode context.
1986 * @param[in,out] pDecodedItem On input the array data item that
1987 * holds the mantissa and exponent. On
1988 * output the decoded mantissa and
1989 * exponent.
1990 *
1991 * @returns Decoding errors from getting primitive data items or
1992 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
1993 *
1994 * When called pDecodedItem must be the array that is tagged as a big
1995 * float or decimal fraction, the array that has the two members, the
1996 * exponent and mantissa.
1997 *
1998 * This will fetch and decode the exponent and mantissa and put the
1999 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002000 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002001static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002002QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002004 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002005
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002006 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002008 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 goto Done;
2010 }
2011
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002012 /* A check for pDecodedItem->val.uCount == 2 would work for
2013 * definite-length arrays, but not for indefnite. Instead remember
2014 * the nesting level the two integers must be at, which is one
2015 * deeper than that of the array.
2016 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002017 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2018
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002019 /* --- Which is it, decimal fraction or a bigfloat? --- */
2020 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002021 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2022
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002023 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002025 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2026 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002027 goto Done;
2028 }
2029 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002030 /* Array is empty or a map/array encountered when expecting an int */
2031 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002032 goto Done;
2033 }
2034 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002035 /* Data arriving as an unsigned int < INT64_MAX has been
2036 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2037 * also means that the only data arriving here of type
2038 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2039 * and thus an error that will get handled in the next else.
2040 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002041 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2042 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002043 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2044 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002045 goto Done;
2046 }
2047
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002048 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002049 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002050 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2051 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052 goto Done;
2053 }
2054 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002055 /* Mantissa missing or map/array encountered when expecting number */
2056 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002057 goto Done;
2058 }
2059 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002060 /* Data arriving as an unsigned int < INT64_MAX has been
2061 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2062 * also means that the only data arriving here of type
2063 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2064 * and thus an error that will get handled in an else below.
2065 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002066 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002067 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2068 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002069 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002070 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002071 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002072 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2073 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2074 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002075 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002076 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2077 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002078 goto Done;
2079 }
2080
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002081 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002082 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002083 /* Extra items in the decimal fraction / big float */
2084 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002085 goto Done;
2086 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002087 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002088
2089Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002090 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002091}
2092#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2093
2094
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002095#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002096/**
2097 * @brief Decode the MIME type tag
2098 *
2099 * @param[in,out] pDecodedItem The item to decode.
2100 *
2101 * Handle the text and binary MIME type tags. Slightly too complicated
2102 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2103 * incorreclty text-only.
2104 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002105static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002106{
2107 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2108 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002109 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002110 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2111 } else {
2112 return QCBOR_ERR_BAD_OPT_TAG;
2113 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002114
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002115 return QCBOR_SUCCESS;
2116}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002117#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002118
2119
Laurence Lundblade3f1318a2021-01-04 18:26:44 -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},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002140#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002141 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2142 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2143 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2144 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002145#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002146 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2147 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2148};
2149
2150
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002151/**
2152 * @brief Process standard CBOR tags whose content is a string
2153 *
2154 * @param[in] uTag The tag.
2155 * @param[in,out] pDecodedItem The data item.
2156 *
2157 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2158 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2159 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2160 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002161 * Process the CBOR tags that whose content is a byte string or a text
2162 * string and for which the string is just passed on to the caller.
2163 *
2164 * This maps the CBOR tag to the QCBOR type and checks the content
2165 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002166 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002167 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002168 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002169static inline QCBORError
2170ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002171{
Laurence Lundblade99615302020-11-29 11:19:47 -08002172 /* This only works on tags that were not mapped; no need for other yet */
2173 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2174 return QCBOR_ERR_UNSUPPORTED;
2175 }
2176
2177 unsigned uIndex;
2178 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2179 if(StringTagMap[uIndex].uTagNumber == uTag) {
2180 break;
2181 }
2182 }
2183
2184 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2185 if(uQCBORType == QCBOR_TYPE_NONE) {
2186 /* repurpose this error to mean, not handled here */
2187 return QCBOR_ERR_UNSUPPORTED;
2188 }
2189
2190 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2191 if(uQCBORType & IS_BYTE_STRING_BIT) {
2192 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2193 }
2194
2195 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002196 return QCBOR_ERR_BAD_OPT_TAG;
2197 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002198
Laurence Lundblade99615302020-11-29 11:19:47 -08002199 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002200 return QCBOR_SUCCESS;
2201}
2202
2203
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002204/**
2205 * @brief Decode tag content for select tags (decoding layer 1).
2206 *
2207 * @param[in] pMe The decode context.
2208 * @param[out] pDecodedItem The decoded item.
2209 *
2210 * @return Decoding error code.
2211 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002212 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2213 * but the whole tag was not decoded. Here, the whole tags (tag number
2214 * and tag content) that are supported by QCBOR are decoded. This is a
2215 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002216 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002217static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002218QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002219{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002220 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002221
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002222 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002223 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002224 goto Done;
2225 }
2226
Laurence Lundblade99615302020-11-29 11:19:47 -08002227 /* When there are no tag numbers for the item, this exits first
2228 * thing and effectively does nothing.
2229 *
2230 * This loops over all the tag numbers accumulated for this item
2231 * trying to decode and interpret them. This stops at the end of
2232 * the list or at the first tag number that can't be interpreted by
2233 * this code. This is effectively a recursive processing of the
2234 * tags number list that handles nested tags.
2235 */
2236 while(1) {
2237 /* Don't bother to unmap tags via QCBORITem.uTags since this
2238 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2239 */
2240 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002241
Laurence Lundblade99615302020-11-29 11:19:47 -08002242 if(uTagToProcess == CBOR_TAG_INVALID16) {
2243 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002244 break;
2245
Laurence Lundblade99615302020-11-29 11:19:47 -08002246 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002247 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002248
Laurence Lundblade93d89472020-10-03 22:30:50 -07002249#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002250 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2251 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002252 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002253#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002254#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002255 } else if(uTagToProcess == CBOR_TAG_MIME ||
2256 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002257 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002258#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002259
Laurence Lundblade99615302020-11-29 11:19:47 -08002260 } else {
2261 /* See if it is a pass-through byte/text string tag; process if so */
2262 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002263
Laurence Lundblade99615302020-11-29 11:19:47 -08002264 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2265 /* It wasn't a pass-through byte/text string tag so it is
2266 * an unknown tag. This is the exit from the loop on the
2267 * first unknown tag. It is a successful exit.
2268 */
2269 uReturn = QCBOR_SUCCESS;
2270 break;
2271 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002272 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002273
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002274 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002275 /* Error exit from the loop */
2276 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002277 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002278
2279 /* A tag was successfully processed, shift it out of the list of
2280 * tags returned. This is the loop increment.
2281 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002282 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002283 }
2284
2285Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002286 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002287}
2288
2289
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002290/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002291 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002292 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002293QCBORError
2294QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2295{
2296 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002297 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002298 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002299 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2300 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2301 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002302 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002303}
2304
2305
2306/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002307 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002308 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002309QCBORError
2310QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2311{
2312 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2313 const UsefulInputBuf Save = pMe->InBuf;
2314
2315 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2316
2317 pMe->nesting = SaveNesting;
2318 pMe->InBuf = Save;
2319
2320 return uErr;
2321}
2322
2323
2324/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002325 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002326 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002327void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2328{
2329 if(pMe->uLastError != QCBOR_SUCCESS) {
2330 return;
2331 }
2332
2333 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2334}
2335
2336
2337/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002338 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002339 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002340QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002341QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2342 QCBORItem *pDecodedItem,
2343 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002344{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002345 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002346
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002347 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2348 if(uReturn != QCBOR_SUCCESS) {
2349 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002350 }
2351
2352 if(pTags != NULL) {
2353 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002354 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002355 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2356 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002357 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002358 }
2359 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2360 return QCBOR_ERR_TOO_MANY_TAGS;
2361 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002362 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002363 pTags->uNumUsed++;
2364 }
2365 }
2366
2367 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002368}
2369
2370
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002371/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002372 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302373 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002374bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002375 const QCBORItem *pItem,
2376 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002377{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002378 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2379 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002380 break;
2381 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002382 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002383 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002384 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002385 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002386
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002387 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002388}
2389
2390
2391/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002392 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002393 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002394QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002395{
Laurence Lundblade87495732021-02-26 10:05:55 -07002396 if(puConsumed != NULL) {
2397 *puConsumed = pMe->InBuf.cursor;
2398 }
2399
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002400 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002401
2402 if(uReturn != QCBOR_SUCCESS) {
2403 goto Done;
2404 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002405
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002406 /* Error out if all the maps/arrays are not closed out */
2407 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002408 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002409 goto Done;
2410 }
2411
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002412 /* Error out if not all the bytes are consumed */
2413 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002414 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002415 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002416
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002417Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002418 return uReturn;
2419}
2420
2421
2422/*
2423 * Public function, see header qcbor/qcbor_decode.h file
2424 */
2425QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2426{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002427#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002428 /* Call the destructor for the string allocator if there is one.
2429 * Always called, even if there are errors; always have to clean up.
2430 */
2431 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002432#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002433
Laurence Lundblade87495732021-02-26 10:05:55 -07002434 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002435}
2436
2437
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002438/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002439 * Public function, see header qcbor/qcbor_decode.h file
2440 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002441// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002442uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2443 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002444 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002445{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002446 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2447 return CBOR_TAG_INVALID64;
2448 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002449 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2450 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002451 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002452 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002453 }
2454}
2455
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002456
Laurence Lundblade9b334962020-08-27 10:55:53 -07002457/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002458 * Public function, see header qcbor/qcbor_decode.h file
2459 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002460uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2461 uint32_t uIndex)
2462{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002463 if(pMe->uLastError != QCBOR_SUCCESS) {
2464 return CBOR_TAG_INVALID64;
2465 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002466 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2467 return CBOR_TAG_INVALID64;
2468 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002469 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002470 }
2471}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002473
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002474
2475
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002476#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002477
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002478/* ===========================================================================
2479 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002480
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002481 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002482 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2483 implements the function type QCBORStringAllocate and allows easy
2484 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002485
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002486 This particular allocator is built-in for convenience. The caller
2487 can implement their own. All of this following code will get
2488 dead-stripped if QCBORDecode_SetMemPool() is not called.
2489
2490 This is a very primitive memory allocator. It does not track
2491 individual allocations, only a high-water mark. A free or
2492 reallocation must be of the last chunk allocated.
2493
2494 The size of the pool and offset to free memory are packed into the
2495 first 8 bytes of the memory pool so we don't have to keep them in
2496 the decode context. Since the address of the pool may not be
2497 aligned, they have to be packed and unpacked as if they were
2498 serialized data of the wire or such.
2499
2500 The sizes packed in are uint32_t to be the same on all CPU types
2501 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002502 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002503
2504
Laurence Lundbladeee851742020-01-08 08:37:05 -08002505static inline int
2506MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002507{
2508 // Use of UsefulInputBuf is overkill, but it is convenient.
2509 UsefulInputBuf UIB;
2510
Laurence Lundbladeee851742020-01-08 08:37:05 -08002511 // Just assume the size here. It was checked during SetUp so
2512 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002513 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002514 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2515 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2516 return UsefulInputBuf_GetError(&UIB);
2517}
2518
2519
Laurence Lundbladeee851742020-01-08 08:37:05 -08002520static inline int
2521MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002522{
2523 // Use of UsefulOutBuf is overkill, but convenient. The
2524 // length check performed here is useful.
2525 UsefulOutBuf UOB;
2526
2527 UsefulOutBuf_Init(&UOB, Pool);
2528 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2529 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2530 return UsefulOutBuf_GetError(&UOB);
2531}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002532
2533
2534/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002535 Internal function for an allocation, reallocation free and destuct.
2536
2537 Having only one function rather than one each per mode saves space in
2538 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002539
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002540 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2541 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002542static UsefulBuf
2543MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002544{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002545 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002546
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002547 uint32_t uPoolSize;
2548 uint32_t uFreeOffset;
2549
2550 if(uNewSize > UINT32_MAX) {
2551 // This allocator is only good up to 4GB. This check should
2552 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2553 goto Done;
2554 }
2555 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2556
2557 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2558 goto Done;
2559 }
2560
2561 if(uNewSize) {
2562 if(pMem) {
2563 // REALLOCATION MODE
2564 // Calculate pointer to the end of the memory pool. It is
2565 // assumed that pPool + uPoolSize won't wrap around by
2566 // assuming the caller won't pass a pool buffer in that is
2567 // not in legitimate memory space.
2568 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2569
2570 // Check that the pointer for reallocation is in the range of the
2571 // pool. This also makes sure that pointer math further down
2572 // doesn't wrap under or over.
2573 if(pMem >= pPool && pMem < pPoolEnd) {
2574 // Offset to start of chunk for reallocation. This won't
2575 // wrap under because of check that pMem >= pPool. Cast
2576 // is safe because the pool is always less than UINT32_MAX
2577 // because of check in QCBORDecode_SetMemPool().
2578 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2579
2580 // Check to see if the allocation will fit. uPoolSize -
2581 // uMemOffset will not wrap under because of check that
2582 // pMem is in the range of the uPoolSize by check above.
2583 if(uNewSize <= uPoolSize - uMemOffset) {
2584 ReturnValue.ptr = pMem;
2585 ReturnValue.len = uNewSize;
2586
2587 // Addition won't wrap around over because uNewSize was
2588 // checked to be sure it is less than the pool size.
2589 uFreeOffset = uMemOffset + uNewSize32;
2590 }
2591 }
2592 } else {
2593 // ALLOCATION MODE
2594 // uPoolSize - uFreeOffset will not underflow because this
2595 // pool implementation makes sure uFreeOffset is always
2596 // smaller than uPoolSize through this check here and
2597 // reallocation case.
2598 if(uNewSize <= uPoolSize - uFreeOffset) {
2599 ReturnValue.len = uNewSize;
2600 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002601 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002602 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002603 }
2604 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002605 if(pMem) {
2606 // FREE MODE
2607 // Cast is safe because of limit on pool size in
2608 // QCBORDecode_SetMemPool()
2609 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2610 } else {
2611 // DESTRUCT MODE
2612 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002613 }
2614 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002615
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002616 UsefulBuf Pool = {pPool, uPoolSize};
2617 MemPool_Pack(Pool, uFreeOffset);
2618
2619Done:
2620 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002621}
2622
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002623
Laurence Lundbladef6531662018-12-04 10:42:22 +09002624/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002625 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002626 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002627QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2628 UsefulBuf Pool,
2629 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002630{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002631 // The pool size and free mem offset are packed into the beginning
2632 // of the pool memory. This compile time check make sure the
2633 // constant in the header is correct. This check should optimize
2634 // down to nothing.
2635 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002636 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002637 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002638
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002639 // The pool size and free offset packed in to the beginning of pool
2640 // memory are only 32-bits. This check will optimize out on 32-bit
2641 // machines.
2642 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002643 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002644 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002645
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002646 // This checks that the pool buffer given is big enough.
2647 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002648 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002649 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002650
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002651 pMe->StringAllocator.pfAllocator = MemPool_Function;
2652 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2653 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002654
Laurence Lundblade30816f22018-11-10 13:40:22 +07002655 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002656}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002657#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002658
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002659
2660
Laurence Lundblade9b334962020-08-27 10:55:53 -07002661static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2662{
2663 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2664}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002665
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002666
2667/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002668 Consume an entire map or array (and do next to
2669 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002670 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002671static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002672ConsumeItem(QCBORDecodeContext *pMe,
2673 const QCBORItem *pItemToConsume,
2674 uint_fast8_t *puNextNestLevel)
2675{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002676 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002677 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002678
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002679 // If it is a map or array, this will tell if it is empty.
2680 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2681
2682 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2683 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002684
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002685 /* This works for definite- and indefinite- length
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 * maps and arrays by using the nesting level
2687 */
2688 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002689 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002690 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002691 goto Done;
2692 }
2693 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002694
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002695 *puNextNestLevel = Item.uNextNestLevel;
2696
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002697 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002698
Laurence Lundblade1341c592020-04-11 14:19:05 -07002699 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002700 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002701 /* Just pass the nesting level through */
2702 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2703
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002704 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002706
2707Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002708 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002709}
2710
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002711
2712void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2713{
2714 uint8_t uNextNestLevel;
2715
2716 QCBORDecode_VGetNext(pMe, pDecodedItem);
2717
2718 if(pMe->uLastError == QCBOR_SUCCESS) {
2719 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem, &uNextNestLevel);
2720 pDecodedItem->uNextNestLevel = uNextNestLevel;
2721 }
2722}
2723
2724
2725
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002726/* Call only on maps and arrays. Rewinds the cursor
2727 * to the start as if it was just entered.
2728 */
2729static void RewindMapOrArray(QCBORDecodeContext *pMe)
2730{
2731 /* Reset nesting tracking to the deepest bounded level */
2732 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2733
2734 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2735
2736 /* Reposition traversal cursor to the start of the map/array */
2737 UsefulInputBuf_Seek(&(pMe->InBuf),
2738 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2739}
2740
2741
2742/*
2743 Public function, see header qcbor/qcbor_decode.h file
2744 */
2745void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2746{
2747 if(pMe->nesting.pCurrentBounded != NULL) {
2748 /* In a bounded map, array or bstr-wrapped CBOR */
2749
2750 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2751 /* In bstr-wrapped CBOR. */
2752
2753 /* Reposition traversal cursor to start of wrapping byte string */
2754 UsefulInputBuf_Seek(&(pMe->InBuf),
2755 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2756 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2757
2758 } else {
2759 /* In a map or array */
2760 RewindMapOrArray(pMe);
2761 }
2762
2763 } else {
2764 /* Not in anything bounded */
2765
2766 /* Reposition traversal cursor to the start of input CBOR */
2767 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2768
2769 /* Reset nesting tracking to beginning of input. */
2770 DecodeNesting_Init(&(pMe->nesting));
2771 }
2772
2773 pMe->uLastError = QCBOR_SUCCESS;
2774}
2775
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002776
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777/* Return true if the labels in Item1 and Item2 are the same.
2778 Works only for integer and string labels. Returns false
2779 for any other type. */
2780static inline bool
2781MatchLabel(QCBORItem Item1, QCBORItem Item2)
2782{
2783 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2784 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2785 return true;
2786 }
2787 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002788 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002789 return true;
2790 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002791 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002792 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2793 return true;
2794 }
2795 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2796 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2797 return true;
2798 }
2799 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002800
Laurence Lundblade1341c592020-04-11 14:19:05 -07002801 /* Other label types are never matched */
2802 return false;
2803}
2804
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002805
2806/*
2807 Returns true if Item1 and Item2 are the same type
2808 or if either are of QCBOR_TYPE_ANY.
2809 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002810static inline bool
2811MatchType(QCBORItem Item1, QCBORItem Item2)
2812{
2813 if(Item1.uDataType == Item2.uDataType) {
2814 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002815 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002816 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002817 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002818 return true;
2819 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002820 return false;
2821}
2822
2823
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002824/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002825 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002826
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002827 @param[in] pMe The decode context to search.
2828 @param[in,out] pItemArray The items to search for and the items found.
2829 @param[out] puOffset Byte offset of last item matched.
2830 @param[in] pCBContext Context for the not-found item call back.
2831 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002832
2833 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2834
Laurence Lundblade93d89472020-10-03 22:30:50 -07002835 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2836 were found for one of the labels being
2837 search for. This duplicate detection is
2838 only performed for items in pItemArray,
2839 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002840
Laurence Lundblade93d89472020-10-03 22:30:50 -07002841 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2842 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002843
2844 @retval Also errors returned by QCBORDecode_GetNext().
2845
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002846 On input pItemArray contains a list of labels and data types
2847 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002848
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002849 On output the fully retrieved items are filled in with
2850 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002851
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002852 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002853
2854 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002855 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002856static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002857MapSearch(QCBORDecodeContext *pMe,
2858 QCBORItem *pItemArray,
2859 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002860 void *pCBContext,
2861 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002862{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002863 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002864 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002865
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002866 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002867 uReturn = pMe->uLastError;
2868 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002869 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002870
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002871 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002872 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2873 /* QCBOR_TYPE_NONE as first item indicates just looking
2874 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002875 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2876 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002877 }
2878
Laurence Lundblade085d7952020-07-24 10:26:30 -07002879 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2880 // It is an empty bounded array or map
2881 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2882 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002883 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002884 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002885 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002886 // Nothing is ever found in an empty array or map. All items
2887 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002888 uReturn = QCBOR_SUCCESS;
2889 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002890 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002891 }
2892
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002893 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002894 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2895
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002896 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002897 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002898
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002899 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002900 Loop over all the items in the map or array. Each item
2901 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002902 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002903 length maps and arrays. The only reason this is ever
2904 called on arrays is to find their end position.
2905
2906 This will always run over all items in order to do
2907 duplicate detection.
2908
2909 This will exit with failure if it encounters an
2910 unrecoverable error, but continue on for recoverable
2911 errors.
2912
2913 If a recoverable error occurs on a matched item, then
2914 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002915 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002916 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002917 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002918 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002919 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002920 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002921
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002922 /* Get the item */
2923 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002924 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002925 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002926 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002927 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002928 goto Done;
2929 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002930 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002931 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002932 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002933 goto Done;
2934 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002935
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002936 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002937 bool bMatched = false;
2938 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2939 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002940 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002941 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2942 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002943 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002944 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002945 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002946 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002947 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002948 goto Done;
2949 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002950
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002951 if(uResult != QCBOR_SUCCESS) {
2952 uReturn = uResult;
2953 goto Done;
2954 }
2955
Laurence Lundblade1341c592020-04-11 14:19:05 -07002956 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002957 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002958 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002959 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002960 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002961 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002962 bMatched = true;
2963 }
2964 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002965
2966
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002967 if(!bMatched && pfCallback != NULL) {
2968 /*
2969 Call the callback on unmatched labels.
2970 (It is tempting to do duplicate detection here, but that would
2971 require dynamic memory allocation because the number of labels
2972 that might be encountered is unbounded.)
2973 */
2974 uReturn = (*pfCallback)(pCBContext, &Item);
2975 if(uReturn != QCBOR_SUCCESS) {
2976 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002977 }
2978 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002979
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002980 /*
2981 Consume the item whether matched or not. This
2982 does the work of traversing maps and array and
2983 everything in them. In this loop only the
2984 items at the current nesting level are examined
2985 to match the labels.
2986 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002987 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002988 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002989 goto Done;
2990 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002991
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002992 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002993
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002994 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002995
2996 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002997
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002998 // Check here makes sure that this won't accidentally be
2999 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003000 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003001 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3002 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003003 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3004 goto Done;
3005 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003006 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3007 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003008
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003009 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003010 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3011
3012 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003013 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003014 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003015 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003016 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3017 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003018 }
3019 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003020
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003021 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003022}
3023
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003024
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003025/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003026 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003028void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3029 int64_t nLabel,
3030 uint8_t uQcborType,
3031 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003032{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003033 if(pMe->uLastError != QCBOR_SUCCESS) {
3034 return;
3035 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003036
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003037 QCBORItem OneItemSeach[2];
3038 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3039 OneItemSeach[0].label.int64 = nLabel;
3040 OneItemSeach[0].uDataType = uQcborType;
3041 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003042
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003043 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003044
3045 *pItem = OneItemSeach[0];
3046
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003047 if(uReturn != QCBOR_SUCCESS) {
3048 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003049 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003050 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003051 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003052 }
3053
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003054 Done:
3055 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003056}
3057
3058
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003059/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003060 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003061*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003062void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3063 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003064 uint8_t uQcborType,
3065 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003066{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003067 if(pMe->uLastError != QCBOR_SUCCESS) {
3068 return;
3069 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003070
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003071 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003072 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3073 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3074 OneItemSeach[0].uDataType = uQcborType;
3075 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003076
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003077 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3078 if(uReturn != QCBOR_SUCCESS) {
3079 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003080 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003081 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003082 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003083 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003084 }
3085
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003086 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003087
3088Done:
3089 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003090}
3091
3092
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003093
Laurence Lundblade93d89472020-10-03 22:30:50 -07003094static QCBORError
3095CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003096{
3097 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3098 if(uDataType == puTypeList[i]) {
3099 return QCBOR_SUCCESS;
3100 }
3101 }
3102 return QCBOR_ERR_UNEXPECTED_TYPE;
3103}
3104
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003105
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003106/**
3107 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003108 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003109
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003110 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3111 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003112
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003113 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3114 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003115 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003116static QCBORError
3117CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003118{
3119 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3120 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3121 /* There are tags that QCBOR couldn't process on this item and
3122 the caller has told us there should not be. */
3123 return QCBOR_ERR_UNEXPECTED_TYPE;
3124 }
3125
3126 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3127 const int nItemType = pItem->uDataType;
3128
3129 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3130 // Must match the tag and only the tag
3131 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3132 }
3133
3134 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3135 if(uReturn == QCBOR_SUCCESS) {
3136 return QCBOR_SUCCESS;
3137 }
3138
3139 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3140 /* Must match the content type and only the content type.
3141 There was no match just above so it is a fail. */
3142 return QCBOR_ERR_UNEXPECTED_TYPE;
3143 }
3144
3145 /* If here it can match either the tag or the content
3146 and it hasn't matched the content, so the end
3147 result is whether it matches the tag. This is
3148 also the case that the CBOR standard discourages. */
3149
3150 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3151}
3152
Laurence Lundblade9b334962020-08-27 10:55:53 -07003153
Laurence Lundblade9b334962020-08-27 10:55:53 -07003154
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003155// This could be semi-private if need be
3156static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003157void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3158 int64_t nLabel,
3159 TagSpecification TagSpec,
3160 QCBORItem *pItem)
3161{
3162 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3163 if(pMe->uLastError != QCBOR_SUCCESS) {
3164 return;
3165 }
3166
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003167 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003168}
3169
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003170
3171// This could be semi-private if need be
3172static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003173void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3174 const char *szLabel,
3175 TagSpecification TagSpec,
3176 QCBORItem *pItem)
3177{
3178 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3179 if(pMe->uLastError != QCBOR_SUCCESS) {
3180 return;
3181 }
3182
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003183 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003184}
3185
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003186// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003187void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3188 int64_t nLabel,
3189 TagSpecification TagSpec,
3190 UsefulBufC *pString)
3191{
3192 QCBORItem Item;
3193 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3194 if(pMe->uLastError == QCBOR_SUCCESS) {
3195 *pString = Item.val.string;
3196 }
3197}
3198
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003199// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003200void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3201 const char * szLabel,
3202 TagSpecification TagSpec,
3203 UsefulBufC *pString)
3204{
3205 QCBORItem Item;
3206 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3207 if(pMe->uLastError == QCBOR_SUCCESS) {
3208 *pString = Item.val.string;
3209 }
3210}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003211
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003212/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003213 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003214*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003215void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003216{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003217 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3218 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003219}
3220
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003221/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003222 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003223*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003224void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3225 QCBORItem *pItemList,
3226 void *pCallbackCtx,
3227 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003228{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003229 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3230 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003231}
3232
3233
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003234/**
3235 * @brief Search for a map/array by label and enter it
3236 *
3237 * @param[in] pMe The decode context.
3238 * @param[in] pSearch The map/array to search for.
3239 *
3240 * @c pSearch is expected to contain one item of type map or array
3241 * with the label specified. The current bounded map will be searched for
3242 * this and if found will be entered.
3243 *
3244 * If the label is not found, or the item found is not a map or array,
3245 * the error state is set.
3246 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003247static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003248{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003249 // The first item in pSearch is the one that is to be
3250 // entered. It should be the only one filled in. Any other
3251 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003252 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003253 return;
3254 }
3255
3256 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003257 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003258 if(pMe->uLastError != QCBOR_SUCCESS) {
3259 return;
3260 }
3261
Laurence Lundblade9b334962020-08-27 10:55:53 -07003262 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003263 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003264 return;
3265 }
3266
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003267
3268 /* The map or array was found. Now enter it.
3269 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003270 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3271 * next item for the pre-order traversal cursor to be the map/array
3272 * found by MapSearch(). The next few lines of code force the
3273 * cursor to that.
3274 *
3275 * There is no need to retain the old cursor because
3276 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3277 * beginning of the map/array being entered.
3278 *
3279 * The cursor is forced by: 1) setting the input buffer position to
3280 * the item offset found by MapSearch(), 2) setting the map/array
3281 * counter to the total in the map/array, 3) setting the nesting
3282 * level. Setting the map/array counter to the total is not
3283 * strictly correct, but this is OK because this cursor only needs
3284 * to be used to get one item and MapSearch() has already found it
3285 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003286 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003287 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003288
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003289 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3290
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003291 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003292
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003293 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003294}
3295
3296
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003297/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003298 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003299*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003300void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003301{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003302 QCBORItem OneItemSeach[2];
3303 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3304 OneItemSeach[0].label.int64 = nLabel;
3305 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3306 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003307
Laurence Lundblade9b334962020-08-27 10:55:53 -07003308 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003309 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003310}
3311
3312
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003313/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003314 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003315*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003316void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003317{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003318 QCBORItem OneItemSeach[2];
3319 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3320 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3321 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3322 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003323
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003324 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003325}
3326
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003327/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003328 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003329*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003330void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003331{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003332 QCBORItem OneItemSeach[2];
3333 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3334 OneItemSeach[0].label.int64 = nLabel;
3335 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3336 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003337
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003338 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003339}
3340
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003341/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003342 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003343*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003344void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3345{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003346 QCBORItem OneItemSeach[2];
3347 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3348 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3349 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3350 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003351
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003352 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003353}
3354
3355
Laurence Lundblade02625d42020-06-25 14:41:41 -07003356// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003357void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003358{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003359 QCBORError uErr;
3360
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003361 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003362 if(pMe->uLastError != QCBOR_SUCCESS) {
3363 // Already in error state; do nothing.
3364 return;
3365 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003366
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003367 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003368 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003369 uErr = QCBORDecode_GetNext(pMe, &Item);
3370 if(uErr != QCBOR_SUCCESS) {
3371 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003372 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003373 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003374 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3375 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003376 }
3377
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003378 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003379
3380
Laurence Lundbladef0499502020-08-01 11:55:57 -07003381 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003382 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003383 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3384 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003385 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003386 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3387 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003388 // Special case to increment nesting level for zero-length maps
3389 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003390 DecodeNesting_Descend(&(pMe->nesting), uType);
3391 }
3392
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003393 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003394
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003395 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3396 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003397
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003398 if(pItem != NULL) {
3399 *pItem = Item;
3400 }
3401
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003402Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003403 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003404}
3405
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406
3407/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003408 This is the common work for exiting a level that is a bounded map,
3409 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003410
3411 One chunk of work is to set up the pre-order traversal so it is at
3412 the item just after the bounded map, array or bstr that is being
3413 exited. This is somewhat complex.
3414
3415 The other work is to level-up the bounded mode to next higest bounded
3416 mode or the top level if there isn't one.
3417 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003418static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003419ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003420{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003421 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003422
Laurence Lundblade02625d42020-06-25 14:41:41 -07003423 /*
3424 First the pre-order-traversal byte offset is positioned to the
3425 item just after the bounded mode item that was just consumed.
3426 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003427 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3428
Laurence Lundblade02625d42020-06-25 14:41:41 -07003429 /*
3430 Next, set the current nesting level to one above the bounded level
3431 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003432
Laurence Lundblade02625d42020-06-25 14:41:41 -07003433 DecodeNesting_CheckBoundedType() is always called before this and
3434 makes sure pCurrentBounded is valid.
3435 */
3436 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3437
3438 /*
3439 This does the complex work of leveling up the pre-order traversal
3440 when the end of a map or array or another bounded level is
3441 reached. It may do nothing, or ascend all the way to the top
3442 level.
3443 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003444 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003445 if(uErr != QCBOR_SUCCESS) {
3446 goto Done;
3447 }
3448
Laurence Lundblade02625d42020-06-25 14:41:41 -07003449 /*
3450 This makes the next highest bounded level the current bounded
3451 level. If there is no next highest level, then no bounded mode is
3452 in effect.
3453 */
3454 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003455
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003456 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003457
3458Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003459 return uErr;
3460}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003461
Laurence Lundblade02625d42020-06-25 14:41:41 -07003462
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003463// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003464void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003465{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003466 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003467 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003468 return;
3469 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003470
Laurence Lundblade02625d42020-06-25 14:41:41 -07003471 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003472
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003473 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003474 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003475 goto Done;
3476 }
3477
Laurence Lundblade02625d42020-06-25 14:41:41 -07003478 /*
3479 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003480 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003481 from previous map search, then do a dummy search.
3482 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003483 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003484 QCBORItem Dummy;
3485 Dummy.uLabelType = QCBOR_TYPE_NONE;
3486 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3487 if(uErr != QCBOR_SUCCESS) {
3488 goto Done;
3489 }
3490 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003491
Laurence Lundblade02625d42020-06-25 14:41:41 -07003492 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003493
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003494Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003495 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003496}
3497
3498
Laurence Lundblade1341c592020-04-11 14:19:05 -07003499
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003500static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003501 const QCBORItem *pItem,
3502 uint8_t uTagRequirement,
3503 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003504{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003505 if(pBstr) {
3506 *pBstr = NULLUsefulBufC;
3507 }
3508
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003509 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003510 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003511 return pMe->uLastError;
3512 }
3513
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003514 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003515
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003516 const TagSpecification TagSpec =
3517 {
3518 uTagRequirement,
3519 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3520 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3521 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003522
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003523 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003524 if(uError != QCBOR_SUCCESS) {
3525 goto Done;
3526 }
3527
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003528 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003529 /* Reverse the decrement done by GetNext() for the bstr so the
3530 * increment in QCBORDecode_NestLevelAscender() called by
3531 * ExitBoundedLevel() will work right.
3532 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003533 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003534 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003535
3536 if(pBstr) {
3537 *pBstr = pItem->val.string;
3538 }
3539
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003540 /* This saves the current length of the UsefulInputBuf and then
3541 * narrows the UsefulInputBuf to start and length of the wrapped
3542 * CBOR that is being entered.
3543 *
3544 * Most of these calls are simple inline accessors so this doesn't
3545 * amount to much code.
3546 */
3547
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003548 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003549 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3550 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003551 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003552 goto Done;
3553 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003554
3555 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3556 pItem->val.string.ptr);
3557 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3558 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3559 /* This should never happen because pItem->val.string.ptr should
3560 * always be valid since it was just returned.
3561 */
3562 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3563 goto Done;
3564 }
3565
3566 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3567
3568 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003569 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003570
Laurence Lundblade02625d42020-06-25 14:41:41 -07003571 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003572 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003573 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003574Done:
3575 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003576}
3577
3578
Laurence Lundblade02625d42020-06-25 14:41:41 -07003579/*
3580 Public function, see header qcbor/qcbor_decode.h file
3581 */
3582void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003583 uint8_t uTagRequirement,
3584 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003585{
3586 if(pMe->uLastError != QCBOR_SUCCESS) {
3587 // Already in error state; do nothing.
3588 return;
3589 }
3590
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003591 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003592 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003593 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3594 if(pMe->uLastError != QCBOR_SUCCESS) {
3595 return;
3596 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003597
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003598 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003599 &Item,
3600 uTagRequirement,
3601 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003602}
3603
3604
Laurence Lundblade02625d42020-06-25 14:41:41 -07003605/*
3606 Public function, see header qcbor/qcbor_decode.h file
3607 */
3608void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003609 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003610 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003611 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003612{
3613 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003614 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003615
Laurence Lundblade93d89472020-10-03 22:30:50 -07003616 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3617 &Item,
3618 uTagRequirement,
3619 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003620}
3621
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003622
Laurence Lundblade02625d42020-06-25 14:41:41 -07003623/*
3624 Public function, see header qcbor/qcbor_decode.h file
3625 */
3626void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003627 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003628 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003629 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003630{
3631 QCBORItem Item;
3632 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3633
Laurence Lundblade93d89472020-10-03 22:30:50 -07003634 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3635 &Item,
3636 uTagRequirement,
3637 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003638}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003639
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003640
Laurence Lundblade02625d42020-06-25 14:41:41 -07003641/*
3642 Public function, see header qcbor/qcbor_decode.h file
3643 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003644void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003645{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003646 if(pMe->uLastError != QCBOR_SUCCESS) {
3647 // Already in error state; do nothing.
3648 return;
3649 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003650
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003651 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003652 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003653 return;
3654 }
3655
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003656 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3657
Laurence Lundblade02625d42020-06-25 14:41:41 -07003658 /*
3659 Reset the length of the UsefulInputBuf to what it was before
3660 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003661 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003662 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003663 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003664
3665
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003666 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003667 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003668}
3669
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003670
Laurence Lundbladee6430642020-03-14 21:15:44 -07003671
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003672
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003673
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003674
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003675
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003676
Laurence Lundblade93d89472020-10-03 22:30:50 -07003677static QCBORError
3678InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003679{
3680 switch(pItem->uDataType) {
3681 case QCBOR_TYPE_TRUE:
3682 *pBool = true;
3683 return QCBOR_SUCCESS;
3684 break;
3685
3686 case QCBOR_TYPE_FALSE:
3687 *pBool = false;
3688 return QCBOR_SUCCESS;
3689 break;
3690
3691 default:
3692 return QCBOR_ERR_UNEXPECTED_TYPE;
3693 break;
3694 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003695 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003696}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003697
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003698
Laurence Lundblade9b334962020-08-27 10:55:53 -07003699
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003700/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003701 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003702*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003704{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003705 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003706 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003707 return;
3708 }
3709
Laurence Lundbladec4537442020-04-14 18:53:22 -07003710 QCBORError nError;
3711 QCBORItem Item;
3712
3713 nError = QCBORDecode_GetNext(pMe, &Item);
3714 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003715 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003716 return;
3717 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003718 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003719}
3720
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003721
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003722/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003723 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003724*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003726{
3727 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003728 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003729
Laurence Lundblade9b334962020-08-27 10:55:53 -07003730 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731}
3732
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003733
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003734/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003735 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003736*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003737void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3738{
3739 QCBORItem Item;
3740 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3741
Laurence Lundblade9b334962020-08-27 10:55:53 -07003742 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003743}
3744
3745
3746
Laurence Lundbladec7114722020-08-13 05:11:40 -07003747
3748static void ProcessEpochDate(QCBORDecodeContext *pMe,
3749 QCBORItem *pItem,
3750 uint8_t uTagRequirement,
3751 int64_t *pnTime)
3752{
3753 if(pMe->uLastError != QCBOR_SUCCESS) {
3754 // Already in error state, do nothing
3755 return;
3756 }
3757
3758 QCBORError uErr;
3759
3760 const TagSpecification TagSpec =
3761 {
3762 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003763 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3764 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003765 };
3766
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003767 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003768 if(uErr != QCBOR_SUCCESS) {
3769 goto Done;
3770 }
3771
3772 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3773 uErr = DecodeDateEpoch(pItem);
3774 if(uErr != QCBOR_SUCCESS) {
3775 goto Done;
3776 }
3777 }
3778
Laurence Lundblade9b334962020-08-27 10:55:53 -07003779 // Save the tags in the last item's tags in the decode context
3780 // for QCBORDecode_GetNthTagOfLast()
3781 CopyTags(pMe, pItem);
3782
Laurence Lundbladec7114722020-08-13 05:11:40 -07003783 *pnTime = pItem->val.epochDate.nSeconds;
3784
3785Done:
3786 pMe->uLastError = (uint8_t)uErr;
3787}
3788
3789
3790void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003791 uint8_t uTagRequirement,
3792 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003793{
3794 if(pMe->uLastError != QCBOR_SUCCESS) {
3795 // Already in error state, do nothing
3796 return;
3797 }
3798
3799 QCBORItem Item;
3800 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3801
3802 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3803}
3804
3805
3806void
3807QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3808 int64_t nLabel,
3809 uint8_t uTagRequirement,
3810 int64_t *pnTime)
3811{
3812 QCBORItem Item;
3813 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3814 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3815}
3816
3817
3818void
3819QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3820 const char *szLabel,
3821 uint8_t uTagRequirement,
3822 int64_t *pnTime)
3823{
3824 QCBORItem Item;
3825 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3826 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3827}
3828
3829
3830
3831
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003832void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3833 TagSpecification TagSpec,
3834 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003835{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003836 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003837 // Already in error state, do nothing
3838 return;
3839 }
3840
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003841 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003842 QCBORItem Item;
3843
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003844 uError = QCBORDecode_GetNext(pMe, &Item);
3845 if(uError != QCBOR_SUCCESS) {
3846 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003847 return;
3848 }
3849
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003850 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003851
3852 if(pMe->uLastError == QCBOR_SUCCESS) {
3853 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003854 } else {
3855 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003856 }
3857}
3858
Laurence Lundbladec4537442020-04-14 18:53:22 -07003859
3860
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003861
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003862static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003863 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003864 UsefulBufC *pValue,
3865 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003866{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003867 const TagSpecification TagSpec =
3868 {
3869 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003870 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3871 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003872 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003873
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003874 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003875 if(uErr != QCBOR_SUCCESS) {
3876 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003877 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003878
3879 *pValue = pItem->val.string;
3880
3881 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3882 *pbIsNegative = false;
3883 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3884 *pbIsNegative = true;
3885 }
3886
3887 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003888}
3889
3890
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003891/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003892 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003893 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003894void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3895 uint8_t uTagRequirement,
3896 UsefulBufC *pValue,
3897 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003898{
3899 if(pMe->uLastError != QCBOR_SUCCESS) {
3900 // Already in error state, do nothing
3901 return;
3902 }
3903
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003904 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003905 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3906 if(uError != QCBOR_SUCCESS) {
3907 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003908 return;
3909 }
3910
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003911 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003912}
3913
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003914
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003915/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003916 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003917*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003918void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3919 int64_t nLabel,
3920 uint8_t uTagRequirement,
3921 UsefulBufC *pValue,
3922 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003923{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003924 QCBORItem Item;
3925 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003926 if(pMe->uLastError != QCBOR_SUCCESS) {
3927 return;
3928 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003929
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003930 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003931}
3932
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003933
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003934/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003935 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003936*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003937void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3938 const char *szLabel,
3939 uint8_t uTagRequirement,
3940 UsefulBufC *pValue,
3941 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003942{
3943 QCBORItem Item;
3944 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003945 if(pMe->uLastError != QCBOR_SUCCESS) {
3946 return;
3947 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003948
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003949 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003950}
3951
3952
3953
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003954
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003955// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003956QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3957 const QCBORItem *pItem,
3958 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003959 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003960{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003961 const TagSpecification TagSpecText =
3962 {
3963 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003964 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3965 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003966 };
3967 const TagSpecification TagSpecBinary =
3968 {
3969 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003970 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3971 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003972 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003973
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003974 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003975
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003976 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003977 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003978 if(pbIsTag257 != NULL) {
3979 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003980 }
3981 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003982 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003983 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003984 if(pbIsTag257 != NULL) {
3985 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003986 }
3987 uReturn = QCBOR_SUCCESS;
3988
3989 } else {
3990 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3991 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003992
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003993 return uReturn;
3994}
3995
Laurence Lundblade93d89472020-10-03 22:30:50 -07003996// Improvement: add methods for wrapped CBOR, a simple alternate
3997// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003998
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003999
4000
4001
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004002#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004003
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004004typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004005
4006
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004007// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004008static QCBORError
4009Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004010{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004011 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004012
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004013 if(uResult != 0) {
4014 /* This loop will run a maximum of 19 times because
4015 * UINT64_MAX < 10 ^^ 19. More than that will cause
4016 * exit with the overflow error
4017 */
4018 for(; nExponent > 0; nExponent--) {
4019 if(uResult > UINT64_MAX / 10) {
4020 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4021 }
4022 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004023 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004024
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004025 for(; nExponent < 0; nExponent++) {
4026 uResult = uResult / 10;
4027 if(uResult == 0) {
4028 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4029 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004030 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004031 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004032 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004033
4034 *puResult = uResult;
4035
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004036 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004037}
4038
4039
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004040// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004041static QCBORError
4042Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004043{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004044 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004045
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004046 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004047
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004048 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004049 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004050 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004051 */
4052 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004053 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004054 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004055 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004056 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004057 nExponent--;
4058 }
4059
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004060 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004061 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004062 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4063 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004064 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004065 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004066 }
4067
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004068 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004069
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004070 return QCBOR_SUCCESS;
4071}
4072
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004073
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004074/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004075 Compute value with signed mantissa and signed result. Works with
4076 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004077 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004078static inline QCBORError ExponentiateNN(int64_t nMantissa,
4079 int64_t nExponent,
4080 int64_t *pnResult,
4081 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004082{
4083 uint64_t uResult;
4084
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004085 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004086 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004087 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4088
4089 // Do the exponentiation of the positive mantissa
4090 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4091 if(uReturn) {
4092 return uReturn;
4093 }
4094
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004095
Laurence Lundblade983500d2020-05-14 11:49:34 -07004096 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4097 of INT64_MIN. This assumes two's compliment representation where
4098 INT64_MIN is one increment farther from 0 than INT64_MAX.
4099 Trying to write -INT64_MIN doesn't work to get this because the
4100 compiler tries to work with an int64_t which can't represent
4101 -INT64_MIN.
4102 */
4103 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4104
4105 // Error out if too large
4106 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004107 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4108 }
4109
4110 // Casts are safe because of checks above
4111 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4112
4113 return QCBOR_SUCCESS;
4114}
4115
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004116
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004117/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004118 Compute value with signed mantissa and unsigned result. Works with
4119 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004120 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004121static inline QCBORError ExponentitateNU(int64_t nMantissa,
4122 int64_t nExponent,
4123 uint64_t *puResult,
4124 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004125{
4126 if(nMantissa < 0) {
4127 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4128 }
4129
4130 // Cast to unsigned is OK because of check for negative
4131 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4132 // Exponentiation is straight forward
4133 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4134}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004135
4136
4137/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004138 Compute value with signed mantissa and unsigned result. Works with
4139 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004140 */
4141static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4142 int64_t nExponent,
4143 uint64_t *puResult,
4144 fExponentiator pfExp)
4145{
4146 return (*pfExp)(uMantissa, nExponent, puResult);
4147}
4148
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004149#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4150
4151
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004152
4153
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004154
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004155static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004156{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004157 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004158
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004159 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004160 const uint8_t *pByte = BigNum.ptr;
4161 size_t uLen = BigNum.len;
4162 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004163 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004164 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004165 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004166 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004167 }
4168
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004169 *pResult = uResult;
4170 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004171}
4172
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004173
Laurence Lundblade887add82020-05-17 05:50:34 -07004174static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004175{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004176 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004177}
4178
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004179
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004180static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004181{
4182 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004183 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4184 if(uError) {
4185 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004186 }
4187 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4188 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004189 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004190}
4191
4192
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004193static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004194{
4195 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004196 /* The negative integer furthest from zero for a C int64_t is
4197 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4198 negative number in CBOR is computed as -n - 1 where n is the
4199 encoded integer, where n is what is in the variable BigNum. When
4200 converting BigNum to a uint64_t, the maximum value is thus
4201 INT64_MAX, so that when it -n - 1 is applied to it the result will
4202 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004203
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004204 -n - 1 <= INT64_MIN.
4205 -n - 1 <= -INT64_MAX - 1
4206 n <= INT64_MAX.
4207 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004208 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004209 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004210 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004211 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004212
4213 /// Now apply -n - 1. The cast is safe because
4214 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4215 // is the largest positive integer that an int64_t can
4216 // represent. */
4217 *pnResult = -(int64_t)uResult - 1;
4218
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004219 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004220}
4221
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004222
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004223
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004224
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004225
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004226/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004227Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004228
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004229\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004230
Laurence Lundblade93d89472020-10-03 22:30:50 -07004231\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4232 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233
4234\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4235
Laurence Lundblade93d89472020-10-03 22:30:50 -07004236\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4237 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004238*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004239static QCBORError
4240ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004241{
4242 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004243 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004245#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004246 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004247 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4248 http://www.cplusplus.com/reference/cmath/llround/
4249 */
4250 // Not interested in FE_INEXACT
4251 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004252 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4253 *pnValue = llround(pItem->val.dfnum);
4254 } else {
4255 *pnValue = lroundf(pItem->val.fnum);
4256 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004257 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4258 // llround() shouldn't result in divide by zero, but catch
4259 // it here in case it unexpectedly does. Don't try to
4260 // distinguish between the various exceptions because it seems
4261 // they vary by CPU, compiler and OS.
4262 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004263 }
4264 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004265 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004266 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004267#else
4268 return QCBOR_ERR_HW_FLOAT_DISABLED;
4269#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004270 break;
4271
4272 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004273 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004274 *pnValue = pItem->val.int64;
4275 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004276 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004277 }
4278 break;
4279
4280 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004281 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004282 if(pItem->val.uint64 < INT64_MAX) {
4283 *pnValue = pItem->val.int64;
4284 } else {
4285 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4286 }
4287 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004288 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004289 }
4290 break;
4291
4292 default:
4293 return QCBOR_ERR_UNEXPECTED_TYPE;
4294 }
4295 return QCBOR_SUCCESS;
4296}
4297
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004298
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004299void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004300 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004301 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004302 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004303{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004304 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004305 return;
4306 }
4307
Laurence Lundbladee6430642020-03-14 21:15:44 -07004308 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004309 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4310 if(uError) {
4311 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004312 return;
4313 }
4314
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004315 if(pItem) {
4316 *pItem = Item;
4317 }
4318
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004319 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004320}
4321
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004323void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4324 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004325 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004326 int64_t *pnValue,
4327 QCBORItem *pItem)
4328{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004329 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004330 if(pMe->uLastError != QCBOR_SUCCESS) {
4331 return;
4332 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004333
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004335}
4336
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004337
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004338void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4339 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004340 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004341 int64_t *pnValue,
4342 QCBORItem *pItem)
4343{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004344 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004345 if(pMe->uLastError != QCBOR_SUCCESS) {
4346 return;
4347 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004348
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004349 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004350}
4351
4352
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004353/*
4354 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004355
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004356 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357
Laurence Lundblade93d89472020-10-03 22:30:50 -07004358 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4359 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360
4361 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4362
Laurence Lundblade93d89472020-10-03 22:30:50 -07004363 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4364 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004365 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004366static QCBORError
4367Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004368{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004369 switch(pItem->uDataType) {
4370
4371 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004372 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004373 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004374 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004375 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004376 }
4377 break;
4378
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004379 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004380 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004381 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004382 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004383 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004384 }
4385 break;
4386
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004387#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4388 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004389 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004390 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004391 pItem->val.expAndMantissa.nExponent,
4392 pnValue,
4393 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004394 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004395 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004396 }
4397 break;
4398
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004399 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004400 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004401 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004402 pItem->val.expAndMantissa.nExponent,
4403 pnValue,
4404 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004405 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004407 }
4408 break;
4409
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004410 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004411 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004412 int64_t nMantissa;
4413 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004414 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4415 if(uErr) {
4416 return uErr;
4417 }
4418 return ExponentiateNN(nMantissa,
4419 pItem->val.expAndMantissa.nExponent,
4420 pnValue,
4421 Exponentitate10);
4422 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004424 }
4425 break;
4426
4427 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004428 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004429 int64_t nMantissa;
4430 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004431 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4432 if(uErr) {
4433 return uErr;
4434 }
4435 return ExponentiateNN(nMantissa,
4436 pItem->val.expAndMantissa.nExponent,
4437 pnValue,
4438 Exponentitate10);
4439 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004440 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004441 }
4442 break;
4443
4444 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004445 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004446 int64_t nMantissa;
4447 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004448 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4449 if(uErr) {
4450 return uErr;
4451 }
4452 return ExponentiateNN(nMantissa,
4453 pItem->val.expAndMantissa.nExponent,
4454 pnValue,
4455 Exponentitate2);
4456 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004457 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004458 }
4459 break;
4460
4461 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004462 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004463 int64_t nMantissa;
4464 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004465 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4466 if(uErr) {
4467 return uErr;
4468 }
4469 return ExponentiateNN(nMantissa,
4470 pItem->val.expAndMantissa.nExponent,
4471 pnValue,
4472 Exponentitate2);
4473 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004475 }
4476 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004477#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4478
Laurence Lundbladee6430642020-03-14 21:15:44 -07004479
Laurence Lundbladec4537442020-04-14 18:53:22 -07004480 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004481 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004482}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004483
4484
Laurence Lundbladec4537442020-04-14 18:53:22 -07004485/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004486 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004487 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004489{
4490 QCBORItem Item;
4491
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004492 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004493
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004494 if(pMe->uLastError == QCBOR_SUCCESS) {
4495 // The above conversion succeeded
4496 return;
4497 }
4498
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004499 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004500 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004501 return;
4502 }
4503
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004505}
4506
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507
4508/*
4509Public function, see header qcbor/qcbor_decode.h file
4510*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004511void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4512 int64_t nLabel,
4513 uint32_t uConvertTypes,
4514 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004515{
4516 QCBORItem Item;
4517
Laurence Lundblade93d89472020-10-03 22:30:50 -07004518 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4519 nLabel,
4520 uConvertTypes,
4521 pnValue,
4522 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004523
4524 if(pMe->uLastError == QCBOR_SUCCESS) {
4525 // The above conversion succeeded
4526 return;
4527 }
4528
4529 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4530 // The above conversion failed in a way that code below can't correct
4531 return;
4532 }
4533
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004534 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004535}
4536
4537
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004538/*
4539Public function, see header qcbor/qcbor_decode.h file
4540*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004541void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4542 const char *szLabel,
4543 uint32_t uConvertTypes,
4544 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004545{
4546 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004547 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4548 szLabel,
4549 uConvertTypes,
4550 pnValue,
4551 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004552
4553 if(pMe->uLastError == QCBOR_SUCCESS) {
4554 // The above conversion succeeded
4555 return;
4556 }
4557
4558 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4559 // The above conversion failed in a way that code below can't correct
4560 return;
4561 }
4562
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004564}
4565
4566
Laurence Lundblade93d89472020-10-03 22:30:50 -07004567static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568{
4569 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004570 case QCBOR_TYPE_DOUBLE:
4571 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004572#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004573 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004574 // Can't use llround here because it will not convert values
4575 // greater than INT64_MAX and less than UINT64_MAX that
4576 // need to be converted so it is more complicated.
4577 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4578 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4579 if(isnan(pItem->val.dfnum)) {
4580 return QCBOR_ERR_FLOAT_EXCEPTION;
4581 } else if(pItem->val.dfnum < 0) {
4582 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4583 } else {
4584 double dRounded = round(pItem->val.dfnum);
4585 // See discussion in DecodeDateEpoch() for
4586 // explanation of - 0x7ff
4587 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4588 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4589 }
4590 *puValue = (uint64_t)dRounded;
4591 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004592 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004593 if(isnan(pItem->val.fnum)) {
4594 return QCBOR_ERR_FLOAT_EXCEPTION;
4595 } else if(pItem->val.fnum < 0) {
4596 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4597 } else {
4598 float fRounded = roundf(pItem->val.fnum);
4599 // See discussion in DecodeDateEpoch() for
4600 // explanation of - 0x7ff
4601 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4602 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4603 }
4604 *puValue = (uint64_t)fRounded;
4605 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004606 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004607 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4608 // round() and roundf() shouldn't result in exceptions here, but
4609 // catch them to be robust and thorough. Don't try to
4610 // distinguish between the various exceptions because it seems
4611 // they vary by CPU, compiler and OS.
4612 return QCBOR_ERR_FLOAT_EXCEPTION;
4613 }
4614
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004615 } else {
4616 return QCBOR_ERR_UNEXPECTED_TYPE;
4617 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004618#else
4619 return QCBOR_ERR_HW_FLOAT_DISABLED;
4620#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004621 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004622
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004623 case QCBOR_TYPE_INT64:
4624 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4625 if(pItem->val.int64 >= 0) {
4626 *puValue = (uint64_t)pItem->val.int64;
4627 } else {
4628 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4629 }
4630 } else {
4631 return QCBOR_ERR_UNEXPECTED_TYPE;
4632 }
4633 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004634
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004635 case QCBOR_TYPE_UINT64:
4636 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4637 *puValue = pItem->val.uint64;
4638 } else {
4639 return QCBOR_ERR_UNEXPECTED_TYPE;
4640 }
4641 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004643 default:
4644 return QCBOR_ERR_UNEXPECTED_TYPE;
4645 }
4646
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004647 return QCBOR_SUCCESS;
4648}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004649
4650
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004651void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004652 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004654 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004655{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004656 if(pMe->uLastError != QCBOR_SUCCESS) {
4657 return;
4658 }
4659
Laurence Lundbladec4537442020-04-14 18:53:22 -07004660 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004661
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004662 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4663 if(uError) {
4664 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004665 return;
4666 }
4667
Laurence Lundbladea826c502020-05-10 21:07:00 -07004668 if(pItem) {
4669 *pItem = Item;
4670 }
4671
Laurence Lundblade93d89472020-10-03 22:30:50 -07004672 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004673}
4674
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004675
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004676void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004678 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679 uint64_t *puValue,
4680 QCBORItem *pItem)
4681{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004682 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004683 if(pMe->uLastError != QCBOR_SUCCESS) {
4684 return;
4685 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686
Laurence Lundblade93d89472020-10-03 22:30:50 -07004687 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688}
4689
4690
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004691void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004694 uint64_t *puValue,
4695 QCBORItem *pItem)
4696{
4697 if(pMe->uLastError != QCBOR_SUCCESS) {
4698 return;
4699 }
4700
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004701 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004702 if(pMe->uLastError != QCBOR_SUCCESS) {
4703 return;
4704 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004705
Laurence Lundblade93d89472020-10-03 22:30:50 -07004706 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004707}
4708
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004709
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004710
Laurence Lundblade93d89472020-10-03 22:30:50 -07004711static QCBORError
4712UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004713{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714 switch(pItem->uDataType) {
4715
4716 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004717 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4719 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004721 }
4722 break;
4723
4724 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004725 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4727 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004728 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729 }
4730 break;
4731
4732#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4733
4734 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004736 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004737 pItem->val.expAndMantissa.nExponent,
4738 puValue,
4739 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004740 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004742 }
4743 break;
4744
4745 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004746 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004747 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4748 pItem->val.expAndMantissa.nExponent,
4749 puValue,
4750 Exponentitate2);
4751 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004752 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753 }
4754 break;
4755
4756 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004757 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004758 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004759 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004760 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761 if(uErr != QCBOR_SUCCESS) {
4762 return uErr;
4763 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004764 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004765 pItem->val.expAndMantissa.nExponent,
4766 puValue,
4767 Exponentitate10);
4768 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004769 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004770 }
4771 break;
4772
4773 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004774 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
4779 break;
4780
4781 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004783 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004784 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004785 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786 if(uErr != QCBOR_SUCCESS) {
4787 return uErr;
4788 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004789 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790 pItem->val.expAndMantissa.nExponent,
4791 puValue,
4792 Exponentitate2);
4793 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 }
4796 break;
4797
4798 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004800 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4801 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004802 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004803 }
4804 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004805#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 default:
4807 return QCBOR_ERR_UNEXPECTED_TYPE;
4808 }
4809}
4810
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004812/*
4813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004814 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004815void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004816{
4817 QCBORItem Item;
4818
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004819 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004820
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004821 if(pMe->uLastError == QCBOR_SUCCESS) {
4822 // The above conversion succeeded
4823 return;
4824 }
4825
4826 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4827 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004828 return;
4829 }
4830
Laurence Lundblade93d89472020-10-03 22:30:50 -07004831 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004832}
4833
Laurence Lundbladec4537442020-04-14 18:53:22 -07004834
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004835/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004836 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004838void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004839 int64_t nLabel,
4840 uint32_t uConvertTypes,
4841 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842{
4843 QCBORItem Item;
4844
Laurence Lundblade93d89472020-10-03 22:30:50 -07004845 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4846 nLabel,
4847 uConvertTypes,
4848 puValue,
4849 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850
4851 if(pMe->uLastError == QCBOR_SUCCESS) {
4852 // The above conversion succeeded
4853 return;
4854 }
4855
4856 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4857 // The above conversion failed in a way that code below can't correct
4858 return;
4859 }
4860
Laurence Lundblade93d89472020-10-03 22:30:50 -07004861 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862}
4863
4864
4865/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004866 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004868void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004869 const char *szLabel,
4870 uint32_t uConvertTypes,
4871 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872{
4873 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004874 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4875 szLabel,
4876 uConvertTypes,
4877 puValue,
4878 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879
4880 if(pMe->uLastError == QCBOR_SUCCESS) {
4881 // The above conversion succeeded
4882 return;
4883 }
4884
4885 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4886 // The above conversion failed in a way that code below can't correct
4887 return;
4888 }
4889
Laurence Lundblade93d89472020-10-03 22:30:50 -07004890 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891}
4892
4893
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004894
4895
Laurence Lundblade9b334962020-08-27 10:55:53 -07004896static QCBORError ConvertDouble(const QCBORItem *pItem,
4897 uint32_t uConvertTypes,
4898 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004899{
4900 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004901 case QCBOR_TYPE_FLOAT:
4902#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4903 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4904 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004905 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004906 *pdValue = (double)pItem->val.fnum;
4907 } else {
4908 return QCBOR_ERR_UNEXPECTED_TYPE;
4909 }
4910 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004911#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004912 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004913#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004914 break;
4915
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004916 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004917 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4918 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004919 *pdValue = pItem->val.dfnum;
4920 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004921 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004922 }
4923 }
4924 break;
4925
4926 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004927#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004928 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004929 // A simple cast seems to do the job with no worry of exceptions.
4930 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004931 *pdValue = (double)pItem->val.int64;
4932
4933 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004934 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004935 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004936#else
4937 return QCBOR_ERR_HW_FLOAT_DISABLED;
4938#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939 break;
4940
4941 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004942#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004943 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004944 // A simple cast seems to do the job with no worry of exceptions.
4945 // There will be precision loss for some values.
4946 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004947 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004948 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004949 }
4950 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004951#else
4952 return QCBOR_ERR_HW_FLOAT_DISABLED;
4953#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004954
4955 default:
4956 return QCBOR_ERR_UNEXPECTED_TYPE;
4957 }
4958
4959 return QCBOR_SUCCESS;
4960}
4961
4962
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004963void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004964 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004965 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004966 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004967{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004968 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004969 return;
4970 }
4971
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004972 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004973
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004974 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004975 if(uError) {
4976 pMe->uLastError = (uint8_t)uError;
4977 return;
4978 }
4979
4980 if(pItem) {
4981 *pItem = Item;
4982 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004983
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004984 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004985}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004986
Laurence Lundbladec4537442020-04-14 18:53:22 -07004987
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004988void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4989 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004990 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004991 double *pdValue,
4992 QCBORItem *pItem)
4993{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004994 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004995 if(pMe->uLastError != QCBOR_SUCCESS) {
4996 return;
4997 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004999 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005000}
5001
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005002
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005003void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5004 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005005 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005006 double *pdValue,
5007 QCBORItem *pItem)
5008{
5009 if(pMe->uLastError != QCBOR_SUCCESS) {
5010 return;
5011 }
5012
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005013 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005014 if(pMe->uLastError != QCBOR_SUCCESS) {
5015 return;
5016 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005017
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005018 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005019}
5020
5021
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005022#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005023static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5024{
5025 double dResult;
5026
5027 dResult = 0.0;
5028 const uint8_t *pByte = BigNum.ptr;
5029 size_t uLen = BigNum.len;
5030 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005031 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005032 while(uLen--) {
5033 dResult = (dResult * 256.0) + (double)*pByte++;
5034 }
5035
5036 return dResult;
5037}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005038#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5039
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005040
Laurence Lundblade93d89472020-10-03 22:30:50 -07005041static QCBORError
5042DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005043{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005044#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005045 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005046 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5047
5048 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005049 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005050
5051#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005052 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005053 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005054 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005055 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5056 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5057 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005058 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005059 }
5060 break;
5061
5062 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005063 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005064 // Underflow gives 0, overflow gives infinity
5065 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5066 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005067 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005068 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005069 }
5070 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005071#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005072
5073 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005074 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005075 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5076 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005077 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005078 }
5079 break;
5080
5081 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005082 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005083 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005084 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005085 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005086 }
5087 break;
5088
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005089#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005090 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005091 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005092 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5093 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5094 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005095 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005096 }
5097 break;
5098
5099 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005100 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005101 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5102 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5103 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005104 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005105 }
5106 break;
5107
5108 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005109 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005110 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5111 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5112 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005113 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005114 }
5115 break;
5116
5117 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005118 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005119 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005120 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5121 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005122 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005123 }
5124 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005125#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5126
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005127 default:
5128 return QCBOR_ERR_UNEXPECTED_TYPE;
5129 }
5130
5131 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005132
5133#else
5134 (void)pItem;
5135 (void)uConvertTypes;
5136 (void)pdValue;
5137 return QCBOR_ERR_HW_FLOAT_DISABLED;
5138#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5139
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005140}
5141
5142
5143/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005144 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005145*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005146void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5147 uint32_t uConvertTypes,
5148 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005149{
5150
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005151 QCBORItem Item;
5152
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005153 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005154
5155 if(pMe->uLastError == QCBOR_SUCCESS) {
5156 // The above conversion succeeded
5157 return;
5158 }
5159
5160 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5161 // The above conversion failed in a way that code below can't correct
5162 return;
5163 }
5164
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005165 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005166}
5167
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005168
5169/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005170 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005171*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005172void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5173 int64_t nLabel,
5174 uint32_t uConvertTypes,
5175 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005176{
5177 QCBORItem Item;
5178
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005179 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005180
5181 if(pMe->uLastError == QCBOR_SUCCESS) {
5182 // The above conversion succeeded
5183 return;
5184 }
5185
5186 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5187 // The above conversion failed in a way that code below can't correct
5188 return;
5189 }
5190
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005191 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005192}
5193
5194
5195/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005196 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005197*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005198void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5199 const char *szLabel,
5200 uint32_t uConvertTypes,
5201 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005202{
5203 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005204 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005205
5206 if(pMe->uLastError == QCBOR_SUCCESS) {
5207 // The above conversion succeeded
5208 return;
5209 }
5210
5211 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5212 // The above conversion failed in a way that code below can't correct
5213 return;
5214 }
5215
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005216 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005217}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005218
5219
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005220
5221
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005222#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005223static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5224{
5225 while((uInt & 0xff00000000000000UL) == 0) {
5226 uInt = uInt << 8;
5227 };
5228
5229 UsefulOutBuf UOB;
5230
5231 UsefulOutBuf_Init(&UOB, Buffer);
5232
5233 while(uInt) {
5234 const uint64_t xx = uInt & 0xff00000000000000UL;
5235 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5236 uInt = uInt << 8;
5237 (void)xx;
5238 }
5239
5240 return UsefulOutBuf_OutUBuf(&UOB);
5241}
5242
5243
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005244static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5245 TagSpecification TagSpec,
5246 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005247{
5248 QCBORError uErr;
5249 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005250 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005251 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005252 if(uErr != QCBOR_SUCCESS) {
5253 goto Done;
5254 }
5255
5256 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5257 break; // Successful exit. Moving on to finish decoding.
5258 }
5259
5260 // The item is an array, which means an undecoded
5261 // mantissa and exponent, so decode it. It will then
5262 // have a different type and exit the loop if.
5263 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5264 if(uErr != QCBOR_SUCCESS) {
5265 goto Done;
5266 }
5267
5268 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005269 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005270 }
5271Done:
5272 return uErr;
5273}
5274
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005275
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005276static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005277 TagSpecification TagSpec,
5278 QCBORItem *pItem,
5279 int64_t *pnMantissa,
5280 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005281{
5282 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005285 if(uErr != QCBOR_SUCCESS) {
5286 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005287 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005288
Laurence Lundblade9b334962020-08-27 10:55:53 -07005289 switch (pItem->uDataType) {
5290
5291 case QCBOR_TYPE_DECIMAL_FRACTION:
5292 case QCBOR_TYPE_BIGFLOAT:
5293 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5294 *pnExponent = pItem->val.expAndMantissa.nExponent;
5295 break;
5296
5297 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5298 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5299 *pnExponent = pItem->val.expAndMantissa.nExponent;
5300 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5301 break;
5302
5303 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5304 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5305 *pnExponent = pItem->val.expAndMantissa.nExponent;
5306 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5307 break;
5308
5309 default:
5310 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5311 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005312
5313 Done:
5314 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005315}
5316
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005317
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005318static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005319 TagSpecification TagSpec,
5320 QCBORItem *pItem,
5321 UsefulBuf BufferForMantissa,
5322 UsefulBufC *pMantissa,
5323 bool *pbIsNegative,
5324 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005325{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005326 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005327
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005328 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005329 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005330 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005331 }
5332
5333 uint64_t uMantissa;
5334
5335 switch (pItem->uDataType) {
5336
5337 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005338 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005339 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5340 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5341 *pbIsNegative = false;
5342 } else {
5343 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5344 *pbIsNegative = true;
5345 }
5346 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5347 *pnExponent = pItem->val.expAndMantissa.nExponent;
5348 break;
5349
5350 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005351 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005352 *pnExponent = pItem->val.expAndMantissa.nExponent;
5353 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5354 *pbIsNegative = false;
5355 break;
5356
5357 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005358 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005359 *pnExponent = pItem->val.expAndMantissa.nExponent;
5360 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5361 *pbIsNegative = true;
5362 break;
5363
5364 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005365 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005366 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005367
5368Done:
5369 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005370}
5371
5372
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005373/*
5374 Public function, see header qcbor/qcbor_decode.h file
5375*/
5376void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5377 uint8_t uTagRequirement,
5378 int64_t *pnMantissa,
5379 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005380{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005381 if(pMe->uLastError != QCBOR_SUCCESS) {
5382 return;
5383 }
5384
5385 QCBORItem Item;
5386 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5387 if(uError) {
5388 pMe->uLastError = (uint8_t)uError;
5389 return;
5390 }
5391
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005392 const TagSpecification TagSpec =
5393 {
5394 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005395 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5396 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5397 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005398 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005399
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005400 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005401}
5402
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005403
5404/*
5405 Public function, see header qcbor/qcbor_decode.h file
5406*/
5407void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005408 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005409 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410 int64_t *pnMantissa,
5411 int64_t *pnExponent)
5412{
5413 if(pMe->uLastError != QCBOR_SUCCESS) {
5414 return;
5415 }
5416
5417 QCBORItem Item;
5418 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5419
5420 const TagSpecification TagSpec =
5421 {
5422 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005423 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5424 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5425 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 };
5427
5428 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5429}
5430
5431
5432/*
5433 Public function, see header qcbor/qcbor_decode.h file
5434*/
5435void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005437 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 int64_t *pnMantissa,
5439 int64_t *pnExponent)
5440{
5441 if(pMe->uLastError != QCBOR_SUCCESS) {
5442 return;
5443 }
5444
5445 QCBORItem Item;
5446 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5447
5448 const TagSpecification TagSpec =
5449 {
5450 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005451 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5452 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5453 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005454 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005455
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005456 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5457}
5458
5459
5460/*
5461 Public function, see header qcbor/qcbor_decode.h file
5462*/
5463void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5464 uint8_t uTagRequirement,
5465 UsefulBuf MantissaBuffer,
5466 UsefulBufC *pMantissa,
5467 bool *pbMantissaIsNegative,
5468 int64_t *pnExponent)
5469{
5470 if(pMe->uLastError != QCBOR_SUCCESS) {
5471 return;
5472 }
5473
5474 QCBORItem Item;
5475 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5476 if(uError) {
5477 pMe->uLastError = (uint8_t)uError;
5478 return;
5479 }
5480
5481 const TagSpecification TagSpec =
5482 {
5483 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005484 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5485 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5486 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005487 };
5488
Laurence Lundblade93d89472020-10-03 22:30:50 -07005489 ProcessMantissaAndExponentBig(pMe,
5490 TagSpec,
5491 &Item,
5492 MantissaBuffer,
5493 pMantissa,
5494 pbMantissaIsNegative,
5495 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005496}
5497
5498
5499/*
5500 Public function, see header qcbor/qcbor_decode.h file
5501*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005502void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005503 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005504 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005505 UsefulBuf BufferForMantissa,
5506 UsefulBufC *pMantissa,
5507 bool *pbIsNegative,
5508 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005509{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005510 if(pMe->uLastError != QCBOR_SUCCESS) {
5511 return;
5512 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005513
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005514 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005515 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005516 if(pMe->uLastError != QCBOR_SUCCESS) {
5517 return;
5518 }
5519
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 const TagSpecification TagSpec =
5521 {
5522 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005523 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5524 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5525 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005526 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005527
Laurence Lundblade93d89472020-10-03 22:30:50 -07005528 ProcessMantissaAndExponentBig(pMe,
5529 TagSpec,
5530 &Item,
5531 BufferForMantissa,
5532 pMantissa,
5533 pbIsNegative,
5534 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005535}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005536
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005537
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005538/*
5539 Public function, see header qcbor/qcbor_decode.h file
5540*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005541void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005542 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005543 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005544 UsefulBuf BufferForMantissa,
5545 UsefulBufC *pMantissa,
5546 bool *pbIsNegative,
5547 int64_t *pnExponent)
5548{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005549 if(pMe->uLastError != QCBOR_SUCCESS) {
5550 return;
5551 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005552
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005553 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005554 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5555 if(pMe->uLastError != QCBOR_SUCCESS) {
5556 return;
5557 }
5558
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005559 const TagSpecification TagSpec =
5560 {
5561 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005562 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5563 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5564 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005565 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005566
5567 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5568}
5569
5570
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005571/*
5572 Public function, see header qcbor/qcbor_decode.h file
5573*/
5574void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5575 uint8_t uTagRequirement,
5576 int64_t *pnMantissa,
5577 int64_t *pnExponent)
5578{
5579 if(pMe->uLastError != QCBOR_SUCCESS) {
5580 return;
5581 }
5582
5583 QCBORItem Item;
5584 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5585 if(uError) {
5586 pMe->uLastError = (uint8_t)uError;
5587 return;
5588 }
5589 const TagSpecification TagSpec =
5590 {
5591 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005592 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5593 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5594 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005595 };
5596
5597 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5598}
5599
5600
5601/*
5602 Public function, see header qcbor/qcbor_decode.h file
5603*/
5604void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005605 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005606 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005607 int64_t *pnMantissa,
5608 int64_t *pnExponent)
5609{
5610 if(pMe->uLastError != QCBOR_SUCCESS) {
5611 return;
5612 }
5613
5614 QCBORItem Item;
5615 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5616 if(pMe->uLastError != QCBOR_SUCCESS) {
5617 return;
5618 }
5619
5620 const TagSpecification TagSpec =
5621 {
5622 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005623 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5624 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5625 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005626 };
5627
5628 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5629}
5630
5631
5632/*
5633 Public function, see header qcbor/qcbor_decode.h file
5634*/
5635void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005636 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005637 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005638 int64_t *pnMantissa,
5639 int64_t *pnExponent)
5640{
5641 if(pMe->uLastError != QCBOR_SUCCESS) {
5642 return;
5643 }
5644
5645 QCBORItem Item;
5646 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5647 if(pMe->uLastError != QCBOR_SUCCESS) {
5648 return;
5649 }
5650
5651 const TagSpecification TagSpec =
5652 {
5653 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005654 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5655 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5656 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005657 };
5658
5659 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5660}
5661
5662
5663/*
5664 Public function, see header qcbor/qcbor_decode.h file
5665*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005666void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5667 uint8_t uTagRequirement,
5668 UsefulBuf MantissaBuffer,
5669 UsefulBufC *pMantissa,
5670 bool *pbMantissaIsNegative,
5671 int64_t *pnExponent)
5672{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005673 if(pMe->uLastError != QCBOR_SUCCESS) {
5674 return;
5675 }
5676
5677 QCBORItem Item;
5678 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5679 if(uError) {
5680 pMe->uLastError = (uint8_t)uError;
5681 return;
5682 }
5683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005684 const TagSpecification TagSpec =
5685 {
5686 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005687 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5688 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5689 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005690 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005691
5692 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005693}
5694
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005695
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005696/*
5697 Public function, see header qcbor/qcbor_decode.h file
5698*/
5699void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005700 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005701 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005702 UsefulBuf BufferForMantissa,
5703 UsefulBufC *pMantissa,
5704 bool *pbIsNegative,
5705 int64_t *pnExponent)
5706{
5707 if(pMe->uLastError != QCBOR_SUCCESS) {
5708 return;
5709 }
5710
5711 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005712 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5713 if(pMe->uLastError != QCBOR_SUCCESS) {
5714 return;
5715 }
5716
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005717 const TagSpecification TagSpec =
5718 {
5719 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005720 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5721 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5722 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005723 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005724
Laurence Lundblade93d89472020-10-03 22:30:50 -07005725 ProcessMantissaAndExponentBig(pMe,
5726 TagSpec,
5727 &Item,
5728 BufferForMantissa,
5729 pMantissa,
5730 pbIsNegative,
5731 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005732}
5733
5734
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005735/*
5736 Public function, see header qcbor/qcbor_decode.h file
5737*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005738void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005739 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005740 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005741 UsefulBuf BufferForMantissa,
5742 UsefulBufC *pMantissa,
5743 bool *pbIsNegative,
5744 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005745{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005746 if(pMe->uLastError != QCBOR_SUCCESS) {
5747 return;
5748 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005749
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005750 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005751 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5752 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005753 return;
5754 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005755
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005756 const TagSpecification TagSpec =
5757 {
5758 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005759 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5760 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5761 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005762 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005763
Laurence Lundblade93d89472020-10-03 22:30:50 -07005764 ProcessMantissaAndExponentBig(pMe,
5765 TagSpec,
5766 &Item,
5767 BufferForMantissa,
5768 pMantissa,
5769 pbIsNegative,
5770 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005771}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005772
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005773#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */