blob: 11584023e32cd5804b7330d8e194158d4969d74c [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade6474c982020-12-26 22:14:34 -080036#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070037
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade6474c982020-12-26 22:14:34 -080039#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
40 * pow(), exp2()
41 */
42#include <fenv.h> /* feclearexcept(), fetestexcept() */
Laurence Lundbladec7114722020-08-13 05:11:40 -070043#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053046/*
Laurence Lundblade6474c982020-12-26 22:14:34 -080047 * This casts away the const-ness of a pointer, usually so it can be
48 * freed or realloced.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049 */
50#define UNCONST_POINTER(ptr) ((void *)(ptr))
51
Laurence Lundbladea9489f82020-09-12 13:50:56 -070052#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070054
Laurence Lundblade6474c982020-12-26 22:14:34 -080055
56
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070057static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070058QCBORItem_IsMapOrArray(const QCBORItem *pMe)
59{
60 const uint8_t uDataType = pMe->uDataType;
61 return uDataType == QCBOR_TYPE_MAP ||
62 uDataType == QCBOR_TYPE_ARRAY ||
63 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
64}
65
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070066static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070067QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
68{
69 if(!QCBORItem_IsMapOrArray(pMe)){
70 return false;
71 }
72
73 if(pMe->val.uCount != 0) {
74 return false;
75 }
76 return true;
77}
78
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070079static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070080QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
81{
82 if(!QCBORItem_IsMapOrArray(pMe)){
83 return false;
84 }
85
86 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
87 return false;
88 }
89 return true;
90}
91
92
Laurence Lundbladeee851742020-01-08 08:37:05 -080093/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070094 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080095 ===========================================================================*/
96
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097/*
Laurence Lundblade6474c982020-12-26 22:14:34 -080098 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
99 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100 */
101
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700102
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700103static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700104DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700106 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800107 /* Limit in DecodeNesting_Descend against more than
108 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700109 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700110 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700111}
112
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700113
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700114static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700116{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700117 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800118 /* Limit in DecodeNesting_Descend against more than
119 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700121 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700122}
123
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700124
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700125static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700126DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700127{
128 return pNesting->pCurrentBounded->u.ma.uStartOffset;
129}
130
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700131
Laurence Lundblade085d7952020-07-24 10:26:30 -0700132static inline bool
133DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
134{
135 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
136 return true;
137 } else {
138 return false;
139 }
140}
141
142
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700143static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700144DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700146 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700147 return true;
148 } else {
149 return false;
150 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700151}
152
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700153
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700154static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700155DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700156{
157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800158 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159 return false;
160 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700161 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800162 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800165 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166 return true;
167}
168
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700169
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700170static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700171DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700172{
173 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800174 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700175 return true;
176 }
177 return false;
178}
179
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700180
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700181static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700182{
183 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
184 return true;
185 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700186 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -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 void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800195 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700196 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800197 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
198 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
199 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700200 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700202
203 if(bIsEmpty) {
204 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
205 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206}
207
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700208
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700209static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700211 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700212}
213
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700215static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700216DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700217{
218 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800219 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220 return false;
221 }
222 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800223 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224 return false;
225 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700226 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800227 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800230 /* Works for both definite and indefinite length maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800231 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
232 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800233 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700234 return false;
235 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800236 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700237 return true;
238}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700239
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700240
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700241static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800244 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700245 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
246 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700247 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700248 return false;
249 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700250}
251
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700252
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700253static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700254DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700255{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
257 return true;
258 } else {
259 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700260 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261}
262
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700263
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700264static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700265DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700266{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700267 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700268 return false;
269 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700270
271 if(pNesting->pCurrentBounded->uLevelType != uType) {
272 return false;
273 }
274
275 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700276}
277
Laurence Lundblade02625d42020-06-25 14:41:41 -0700278
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700279static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700280DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700281{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800282 /* Only call on a defnite length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700283 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700284}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700285
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700286
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700287static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700288DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
289{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800290 /* Only call on a defnite length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700291 pNesting->pCurrent->u.ma.uCountCursor++;
292}
293
294
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700295static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700296DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
297{
298 pNesting->pCurrent--;
299}
300
Laurence Lundblade02625d42020-06-25 14:41:41 -0700301
302static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700303DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700304{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800305 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700306 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700307 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308 }
309
Laurence Lundblade6474c982020-12-26 22:14:34 -0800310 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311 pNesting->pCurrent++;
312
313 pNesting->pCurrent->uLevelType = uType;
314
315 return QCBOR_SUCCESS;
316}
317
318
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700319static inline QCBORError
Laurence Lundblade6474c982020-12-26 22:14:34 -0800320DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
321 bool bIsEmpty,
322 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700323{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700324 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800325 * Should only be called on map/array.
326 *
327 * Have descended into this before this is called. The job here is
328 * just to mark it in bounded mode.
329 *
330 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
331 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700332 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700333 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700334 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700335 }
336
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700337 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700338
339 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700340
341 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700342}
343
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700344
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700345static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700346DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 uint8_t uQCBORType,
348 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700351
352 if(uCount == 0) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800353 /* Nothing to do for empty definite lenth arrays. They are just are
354 * effectively the same as an item that is not a map or array.
355 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700356 goto Done;
Laurence Lundblade6474c982020-12-26 22:14:34 -0800357 /* Empty indefinite length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358 }
359
Laurence Lundblade6474c982020-12-26 22:14:34 -0800360 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
362 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700363 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700364 goto Done;
365 }
366
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700367 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700368 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700369 goto Done;
370 }
371
Laurence Lundblade6474c982020-12-26 22:14:34 -0800372 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700373 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
374 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700375
376 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700377
378Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700379 return uError;;
380}
381
382
383static inline void
384DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
385{
386 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
387}
388
389
390static inline void
391DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
392{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700393 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700394 pNesting->pCurrentBounded--;
395 if(DecodeNesting_IsCurrentBounded(pNesting)) {
396 break;
397 }
398 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700399}
400
Laurence Lundblade6474c982020-12-26 22:14:34 -0800401
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700402static inline void
403DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
404{
405 pNesting->pCurrent = pNesting->pCurrentBounded;
406}
407
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700408
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700409static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700410DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700411 uint32_t uEndOffset,
412 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700415
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700416 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418 goto Done;
419 }
420
Laurence Lundblade6474c982020-12-26 22:14:34 -0800421 /* Fill in the new byte string level */
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700422 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
423 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424
Laurence Lundblade6474c982020-12-26 22:14:34 -0800425 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700426 pNesting->pCurrentBounded = pNesting->pCurrent;
427
428Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700429 return uError;;
430}
431
Laurence Lundbladed0304932020-06-27 10:59:38 -0700432
433static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700434DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700435{
436 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700437}
438
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700439
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700440static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800441DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
442{
443 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
444}
445
446
447static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700448DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700450 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700451 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
452 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700453}
454
455
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700456static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800457DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
458 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700459{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700460 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700461 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800462 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700463}
464
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465
Laurence Lundblade02625d42020-06-25 14:41:41 -0700466static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800467DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
468 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700469{
470 *pNesting = *pSave;
471}
472
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700475DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476{
477 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
478}
479
480
Laurence Lundblade02625d42020-06-25 14:41:41 -0700481static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700482DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700483{
484 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
485}
486
487
Laurence Lundblade6474c982020-12-26 22:14:34 -0800488
489
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800490#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800491/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
493
494 The following four functions are pretty wrappers for invocation of
495 the string allocator supplied by the caller.
496
Laurence Lundbladeee851742020-01-08 08:37:05 -0800497 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499static inline void
500StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800501{
502 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
503}
504
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505// StringAllocator_Reallocate called with pMem NULL is
506// equal to StringAllocator_Allocate()
507static inline UsefulBuf
508StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
509 void *pMem,
510 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800511{
512 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
513}
514
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515static inline UsefulBuf
516StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800517{
518 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
519}
520
Laurence Lundbladeee851742020-01-08 08:37:05 -0800521static inline void
522StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800523{
524 if(pMe->pfAllocator) {
525 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
526 }
527}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800528#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800529
530
Laurence Lundblade6474c982020-12-26 22:14:34 -0800531
532
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533/*===========================================================================
534 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800536 See qcbor/qcbor_decode.h for definition of the object
537 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800540 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700541 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542void QCBORDecode_Init(QCBORDecodeContext *me,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800543 UsefulBufC EncodedCBOR,
544 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545{
546 memset(me, 0, sizeof(QCBORDecodeContext));
547 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800548 /* Don't bother with error check on decode mode. If a bad value is
549 * passed it will just act as if the default normal mode of 0 was set.
550 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700551 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700552 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700553 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700554 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700555 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556}
557
558
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800559#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
560
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800562 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700563 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800564void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
565 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800566 void *pAllocateContext,
567 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700568{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800569 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
570 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
571 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700572}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800573#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700574
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800575
Laurence Lundblade6474c982020-12-26 22:14:34 -0800576
577
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800579 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800580 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800581void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700583{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800584 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700585 (void)pMe;
586 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700587}
588
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589
590/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591 This decodes the fundamental part of a CBOR data item, the type and
592 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800593
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700594 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800595
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 This does the network->host byte order conversion. The conversion
597 here also results in the conversion for floats in addition to that
598 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700600 This returns:
601 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800602
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800603 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800604 tags and floats and length for strings and arrays
605
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800609 The int type is preferred to uint8_t for some variables as this
610 avoids integer promotions, can reduce code size and makes
611 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700612
613 @retval QCBOR_ERR_UNSUPPORTED
614
615 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700617static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618 int *pnMajorType,
619 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700622 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800623
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700624 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800625 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 const int nTmpMajorType = nInitialByte >> 5;
629 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800630
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800631 // Where the number or argument accumulates
632 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800634 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700635 // Need to get 1,2,4 or 8 additional argument bytes. Map
636 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800637 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800639 // Loop getting all the bytes in the argument
640 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // This shift and add gives the endian conversion
643 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
644 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646 // The reserved and thus-far unused additional info values
647 nReturn = QCBOR_ERR_UNSUPPORTED;
648 goto Done;
649 } else {
650 // Less than 24, additional info is argument or 31, an indefinite length
651 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800654
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655 if(UsefulInputBuf_GetError(pUInBuf)) {
656 nReturn = QCBOR_ERR_HIT_END;
657 goto Done;
658 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700660 // All successful if we got here.
661 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800662 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800663 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666Done:
667 return nReturn;
668}
669
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800672 CBOR doesn't explicitly specify two's compliment for integers but all
673 CPUs use it these days and the test vectors in the RFC are so. All
674 integers in the CBOR structure are positive and the major type
675 indicates positive or negative. CBOR can express positive integers
676 up to 2^x - 1 where x is the number of bits and negative integers
677 down to 2^x. Note that negative numbers can be one more away from
678 zero than positive. Stdint, as far as I can tell, uses two's
679 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800680
Laurence Lundblade9b334962020-08-27 10:55:53 -0700681 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 used carefully here, and in particular why it isn't used in the interface.
683 Also see
684 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
685
686 Int is used for values that need less than 16-bits and would be subject
687 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700688
689 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700690 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700691static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800692DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700694 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
697 if (uNumber <= INT64_MAX) {
698 pDecodedItem->val.int64 = (int64_t)uNumber;
699 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 } else {
702 pDecodedItem->val.uint64 = uNumber;
703 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700705 }
706 } else {
707 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800708 // CBOR's representation of negative numbers lines up with the
709 // two-compliment representation. A negative integer has one
710 // more in range than a positive integer. INT64_MIN is
711 // equal to (-INT64_MAX) - 1.
712 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 } else {
716 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000717 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 nReturn = QCBOR_ERR_INT_OVERFLOW;
719 }
720 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 return nReturn;
723}
724
725// Make sure #define value line up as DecodeSimple counts on this.
726#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
727#error QCBOR_TYPE_FALSE macro value wrong
728#endif
729
730#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
731#error QCBOR_TYPE_TRUE macro value wrong
732#endif
733
734#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
735#error QCBOR_TYPE_NULL macro value wrong
736#endif
737
738#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
739#error QCBOR_TYPE_UNDEF macro value wrong
740#endif
741
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700742#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
743#error QCBOR_TYPE_BREAK macro value wrong
744#endif
745
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
747#error QCBOR_TYPE_DOUBLE macro value wrong
748#endif
749
750#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
751#error QCBOR_TYPE_FLOAT macro value wrong
752#endif
753
754/*
755 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700756
757 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
758
759 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700761static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800762DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700764 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800765
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700766 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800767 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700768 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
769 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800770 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800771
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800773 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
774 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700776 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700777#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700778 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700779 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700780 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700781 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
782 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700783#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700784 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700785#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700786 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700787 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700788 // Single precision is normally returned as a double
789 // since double is widely supported, there is no loss of
790 // precision, it makes it easy for the caller in
791 // most cases and it can be converted back to single
792 // with no loss of precision
793 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700794 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700795 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700796 {
797 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
798#ifndef QCBOR_DISABLE_FLOAT_HW_USE
799 // In the normal case, use HW to convert float to double.
800 pDecodedItem->val.dfnum = (double)f;
801 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700802#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700803 // Use of float HW is disabled, return as a float.
804 pDecodedItem->val.fnum = f;
805 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
806
807 // IEEE754_FloatToDouble() could be used here to return
808 // as a double, but it adds object code and most likely
809 // anyone disabling FLOAT HW use doesn't care about
810 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700811#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700812 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700813 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700814
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700815 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700816 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700817 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700818 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800819
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 case CBOR_SIMPLEV_FALSE: // 20
821 case CBOR_SIMPLEV_TRUE: // 21
822 case CBOR_SIMPLEV_NULL: // 22
823 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700824 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 case CBOR_SIMPLEV_ONEBYTE: // 24
828 if(uNumber <= CBOR_SIMPLE_BREAK) {
829 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700830 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831 goto Done;
832 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800833 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 default: // 0-19
837 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800838 /*
839 DecodeTypeAndNumber will make uNumber equal to
840 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
841 safe because the 2, 4 and 8 byte lengths of uNumber are in
842 the double/float cases above
843 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844 pDecodedItem->val.uSimple = (uint8_t)uNumber;
845 break;
846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848Done:
849 return nReturn;
850}
851
852
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700853/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530854 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700855
856 @retval QCBOR_ERR_HIT_END
857
858 @retval QCBOR_ERR_STRING_ALLOCATE
859
860 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700861 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700862static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800863 uint64_t uStrLen,
864 UsefulInputBuf *pUInBuf,
865 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700867 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800868
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800869 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
870 // This check makes the casts to size_t below safe.
871
872 // 4 bytes less than the largest sizeof() so this can be tested by
873 // putting a SIZE_MAX length in the CBOR test input (no one will
874 // care the limit on strings is 4 bytes shorter).
875 if(uStrLen > SIZE_MAX-4) {
876 nReturn = QCBOR_ERR_STRING_TOO_LONG;
877 goto Done;
878 }
879
880 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530881 if(UsefulBuf_IsNULLC(Bytes)) {
882 // Failed to get the bytes for this string item
883 nReturn = QCBOR_ERR_HIT_END;
884 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530886
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800887#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800888 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800890 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700892 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530893 goto Done;
894 }
895 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800896 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800897 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530898 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800899#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
900 (void)pAllocator;
901#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
902
903 // Normal case with no string allocator
904 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530906Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700907 return nReturn;
908}
909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800911/* Map the CBOR major types for strings to the QCBOR types for strngs */
912static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
913{
914 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
915 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
916 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800917
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800918 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
919 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
920 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800922 return (uint8_t)(nCBORMajorType + 4);
923}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924
925
Laurence Lundbladeee851742020-01-08 08:37:05 -0800926// Make sure the constants align as this is assumed by
927// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
929#error QCBOR_TYPE_ARRAY value not lined up with major type
930#endif
931#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
932#error QCBOR_TYPE_MAP value not lined up with major type
933#endif
934
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800936 This gets a single data item and decodes it including preceding
937 optional tagging. This does not deal with arrays and maps and nesting
938 except to decode the data item introducing them. Arrays and maps are
939 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundbladeee851742020-01-08 08:37:05 -0800941 Errors detected here include: an array that is too long to decode,
942 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700943
944 @retval QCBOR_ERR_UNSUPPORTED
945
946 @retval QCBOR_ERR_HIT_END
947
948 @retval QCBOR_ERR_INT_OVERFLOW
949
950 @retval QCBOR_ERR_STRING_ALLOCATE
951
952 @retval QCBOR_ERR_STRING_TOO_LONG
953
954 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
955
956 @retval QCBOR_ERR_BAD_TYPE_7
957
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800959static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
960 QCBORItem *pDecodedItem,
961 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700963 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 /*
966 Get the major type and the number. Number could be length of more
967 bytes or the value depending on the major type nAdditionalInfo is
968 an encoding of the length of the uNumber and is needed to decode
969 floats and doubles
970 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100971 int nMajorType = 0;
972 uint64_t uNumber = 0;
973 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700975 memset(pDecodedItem, 0, sizeof(QCBORItem));
976
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800977 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundbladeee851742020-01-08 08:37:05 -0800979 // Error out here if we got into trouble on the type and number. The
980 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700981 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700983 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundbladeee851742020-01-08 08:37:05 -0800985 // At this point the major type and the value are valid. We've got
986 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800987 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
989 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800990 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700991 nReturn = QCBOR_ERR_BAD_INT;
992 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800993 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700994 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800996
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700997 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
998 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800999 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001001 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001003 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 }
1005 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1008 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1009 // Record the number of items in the array or map
1010 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001011 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 goto Done;
1013 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001015 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001017 // type conversion OK because of check above
1018 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001021 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001022 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001026 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001027 nReturn = QCBOR_ERR_BAD_INT;
1028 } else {
1029 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001030 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001031 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001033
Laurence Lundbladeee851742020-01-08 08:37:05 -08001034 case CBOR_MAJOR_TYPE_SIMPLE:
1035 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001036 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001038
Laurence Lundbladeee851742020-01-08 08:37:05 -08001039 default:
1040 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041 nReturn = QCBOR_ERR_UNSUPPORTED;
1042 break;
1043 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045Done:
1046 return nReturn;
1047}
1048
1049
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001050/**
1051 * @brief Process indefinite length strings
1052 *
1053 * @param[in] pMe Decoder context
1054 * @param[in,out] pDecodedItem The decoded item that work is done on.
1055 *
1056 * @retval QCBOR_ERR_UNSUPPORTED
1057 * @retval QCBOR_ERR_HIT_END
1058 * @retval QCBOR_ERR_INT_OVERFLOW
1059 * @retval QCBOR_ERR_STRING_ALLOCATE
1060 * @retval QCBOR_ERR_STRING_TOO_LONG
1061 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1062 * @retval QCBOR_ERR_BAD_TYPE_7
1063 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1064 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1065 *
1066 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1067 *
1068 * If it is, this loops getting the subsequent chunks that make up the
1069 * string. The string allocator is used to make a contiguous buffer for
1070 * the chunks. When this completes @c pDecodedItem contains the
1071 * put-together string.
1072 *
1073 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001075static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001076GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001077{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001078 /* Aproximate stack usage
1079 * 64-bit 32-bit
1080 * local vars 32 16
1081 * 2 UsefulBufs 32 16
1082 * QCBORItem 56 52
1083 * TOTAL 120 74
1084 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001085
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001086 /* The string allocator is used here for two purposes: 1)
1087 * coalescing the chunks of an indefinite length string, 2)
1088 * allocating storage for every string returned.
1089 *
1090 * The first use is below in this function. Indefinite length
1091 * strings cannot be processed at all without a string allocator.
1092 *
1093 * The second used is in DecodeBytes() which is called by
1094 * GetNext_Item() below. This second use unneccessary for most use
1095 * and only happens when requested in the call to
1096 * QCBORDecode_SetMemPool(). If the second use not requested then
1097 * NULL is passed for the string allocator to GetNext_Item().
1098 *
1099 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1100 * allocator altogether and thus both of these uses. It reduced the
1101 * decoder object code by about 400 bytes.
1102 */
1103 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001104
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001105#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1106 const QCORInternalAllocator *pAllocator = NULL;
1107
1108 if(pMe->StringAllocator.pfAllocator) {
1109 pAllocator = &(pMe->StringAllocator);
1110 if(pMe->bStringAllocateAll) {
1111 pAllocatorForGetNext = pAllocator;
1112 }
1113 }
1114#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1115
1116 QCBORError uReturn;
1117 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1118 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001119 goto Done;
1120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001122 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001123 const uint8_t uStringType = pDecodedItem->uDataType;
1124 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 goto Done;
1126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001128 /* Is this a string with an indefinite length? */
1129 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1130 goto Done;
1131 }
1132
1133#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1134 /* Can't do indefinite length strings without a string allocator */
1135 if(pAllocator == NULL) {
1136 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1137 goto Done;
1138 }
1139
1140 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001141 UsefulBufC FullString = NULLUsefulBufC;
1142
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001143 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001144 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001145 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001146 /* Pass a NULL string allocator to GetNext_Item() because the
1147 * individual string chunks in an indefinite length should not
1148 * be allocated. They are always copied in the the contiguous
1149 * buffer allocated here.
1150 */
1151 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1152 if(uReturn) {
1153 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001154 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001156 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001157 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001158 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301160 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001161 break;
1162 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001163
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001164 /* All chunks must be of the same type, the type of the item
1165 * that introduces the indefinite length string. This also
1166 * catches errors where the chunk is not a string at all and an
1167 * indefinite length string inside an indefinite length string.
1168 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001169 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001170 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1171 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001172 break;
1173 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001175 /* The first time throurgh FullString.ptr is NULL and this is
1176 * equivalent to StringAllocator_Allocate(). Subsequently it is
1177 * not NULL and a reallocation happens.
1178 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001179 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1180 UNCONST_POINTER(FullString.ptr),
1181 FullString.len + StringChunkItem.val.string.len);
1182
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001183 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001185 break;
1186 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001187
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001188 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001189 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001192 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1193 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001194 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001195 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001196#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1197 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1198#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001200Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001201 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001202}
1203
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204
Laurence Lundblade9b334962020-08-27 10:55:53 -07001205static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001206 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208 } else if(uTagVal == CBOR_TAG_INVALID16) {
1209 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001210 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001211 // This won't be negative because of code below in GetNext_TaggedItem()
1212 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1213 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 }
1215}
1216
Laurence Lundblade9b334962020-08-27 10:55:53 -07001217
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001218/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001219 Gets all optional tag data items preceding a data item that is not an
1220 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001221
1222 @retval QCBOR_ERR_UNSUPPORTED
1223
1224 @retval QCBOR_ERR_HIT_END
1225
1226 @retval QCBOR_ERR_INT_OVERFLOW
1227
1228 @retval QCBOR_ERR_STRING_ALLOCATE
1229
1230 @retval QCBOR_ERR_STRING_TOO_LONG
1231
1232 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1233
1234 @retval QCBOR_ERR_BAD_TYPE_7
1235
1236 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1237
1238 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1239
1240 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001241 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001242static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001243GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001245 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1246 CBOR_TAG_INVALID16,
1247 CBOR_TAG_INVALID16,
1248 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001249
Laurence Lundblade9b334962020-08-27 10:55:53 -07001250 QCBORError uReturn = QCBOR_SUCCESS;
1251
Laurence Lundblade59289e52019-12-30 13:44:37 -08001252 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001253 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001254 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1255 if(uErr != QCBOR_SUCCESS) {
1256 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001257 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001259
Laurence Lundblade9b334962020-08-27 10:55:53 -07001260 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001261 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001262 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001263 break;
1264 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001265
Laurence Lundblade9b334962020-08-27 10:55:53 -07001266 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1267 // No room in the tag list
1268 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1269 // Continue on to get all tags on this item even though
1270 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001271 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001272 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001273 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001274 // Slide tags over one in the array to make room at index 0
1275 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1276 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001278
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001279 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001280 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001282 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001283 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001284 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001285 break;
1286 }
1287 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1288 break;
1289 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001290 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001291 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1292 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001293 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1294 // Continue on to get all tags on this item even though
1295 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001296 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001297 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001298 }
1299
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001300 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001301 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001302 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001303
1304 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001305 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001306 }
1307 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001308
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001309Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001310 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001311}
1312
1313
1314/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001315 This layer takes care of map entries. It combines the label and data
1316 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001317
1318 @retval QCBOR_ERR_UNSUPPORTED
1319
1320 @retval QCBOR_ERR_HIT_END
1321
1322 @retval QCBOR_ERR_INT_OVERFLOW
1323
1324 @retval QCBOR_ERR_STRING_ALLOCATE
1325
1326 @retval QCBOR_ERR_STRING_TOO_LONG
1327
1328 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1329
1330 @retval QCBOR_ERR_BAD_TYPE_7
1331
1332 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1333
1334 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1335
1336 @retval QCBOR_ERR_TOO_MANY_TAGS
1337
1338 @retval QCBOR_ERR_MAP_LABEL_TYPE
1339
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001340 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001341 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001342static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001343GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001344{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001345 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001346 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001347 if(nReturn)
1348 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001349
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001350 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001351 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001352 goto Done;
1353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001355 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1356 // In a map and caller wants maps decoded, not treated as arrays
1357
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001358 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001359 // If in a map and the right decoding mode, get the label
1360
Laurence Lundbladeee851742020-01-08 08:37:05 -08001361 // Save label in pDecodedItem and get the next which will
1362 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001363 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001364 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001365 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001366 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001367 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001368
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301369 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001370
1371 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1372 // strings are always good labels
1373 pDecodedItem->label.string = LabelItem.val.string;
1374 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1375 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001376 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001377 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1378 goto Done;
1379 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1380 pDecodedItem->label.int64 = LabelItem.val.int64;
1381 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1382 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1383 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1384 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1385 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1386 pDecodedItem->label.string = LabelItem.val.string;
1387 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1388 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1389 } else {
1390 // label is not an int or a string. It is an arrray
1391 // or a float or such and this implementation doesn't handle that.
1392 // Also, tags on labels are ignored.
1393 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1394 goto Done;
1395 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001396 }
1397 } else {
1398 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001399 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001400 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001401 goto Done;
1402 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001403 // Decoding a map as an array
1404 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001405 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1406 // Cast is needed because of integer promotion
1407 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001408 }
1409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001410
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001411Done:
1412 return nReturn;
1413}
1414
1415
Laurence Lundblade02625d42020-06-25 14:41:41 -07001416/*
1417 See if next item is a CBOR break. If it is, it is consumed,
1418 if not it is not consumed.
1419*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001420static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001421NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1422{
1423 *pbNextIsBreak = false;
1424 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001425 QCBORItem Peek;
1426 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1427 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1428 if(uReturn != QCBOR_SUCCESS) {
1429 return uReturn;
1430 }
1431 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001432 // It is not a break, rewind so it can be processed normally.
1433 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001434 } else {
1435 *pbNextIsBreak = true;
1436 }
1437 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001438
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001439 return QCBOR_SUCCESS;
1440}
1441
1442
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001443/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001444 An item was just consumed, now figure out if it was the
1445 end of an array or map that can be closed out. That
1446 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001448static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001449{
1450 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001451
Laurence Lundblade642282a2020-06-23 12:00:33 -07001452 /* This loops ascending nesting levels as long as there is ascending to do */
1453 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1454
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001455 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001456 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001457 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1458 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001459 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 break;
1461 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001462 /* All of a definite length array was consumed; fall through to
1463 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001465 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001467 bool bIsBreak = false;
1468 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1469 if(uReturn != QCBOR_SUCCESS) {
1470 goto Done;
1471 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001472
1473 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001474 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001475 break;
1476 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001478 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001479 /*
1480 Break occurred inside a bstr-wrapped CBOR or
1481 in the top level sequence. This is always an
1482 error because neither are an indefinte length
1483 map/array.
1484 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001485 uReturn = QCBOR_ERR_BAD_BREAK;
1486 goto Done;
1487 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001488
Laurence Lundblade02625d42020-06-25 14:41:41 -07001489 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001490 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001491
Laurence Lundblade02625d42020-06-25 14:41:41 -07001492 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001493
Laurence Lundblade93d89472020-10-03 22:30:50 -07001494 /* But ascent in bounded mode is only by explicit call to
1495 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001496 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001497 /* Set the count to zero for definite length arrays to indicate
1498 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001499 if(bMarkEnd) {
1500 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001501 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001502
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001503 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001504 break;
1505 }
1506
1507 /* Finally, actually ascend one level. */
1508 DecodeNesting_Ascend(&(pMe->nesting));
1509 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001510
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001511 uReturn = QCBOR_SUCCESS;
1512
1513Done:
1514 return uReturn;
1515}
1516
1517
1518/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001519 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001520 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1521 indefinte length maps and arrays by looking at the item count or
1522 finding CBOR breaks. It detects the ends of the top-level sequence
1523 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001524
1525 @retval QCBOR_ERR_UNSUPPORTED X
1526
1527 @retval QCBOR_ERR_HIT_END
1528
1529 @retval QCBOR_ERR_INT_OVERFLOW X
1530
1531 @retval QCBOR_ERR_STRING_ALLOCATE
1532
1533 @retval QCBOR_ERR_STRING_TOO_LONG
1534
1535 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1536
1537 @retval QCBOR_ERR_BAD_TYPE_7 X
1538
1539 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1540
1541 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1542
1543 @retval QCBOR_ERR_TOO_MANY_TAGS
1544
1545 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1546
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001547 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001548
1549 @retval QCBOR_ERR_NO_MORE_ITEMS
1550
1551 @retval QCBOR_ERR_BAD_BREAK
1552
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001553 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001554static QCBORError
1555QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001556{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001557 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001558 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001559
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 /*
1561 If out of bytes to consume, it is either the end of the top-level
1562 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001563
Laurence Lundblade642282a2020-06-23 12:00:33 -07001564 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1565 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1566 CBOR is exited, the length is set back to the top-level's length
1567 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001568 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001569 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001570 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001571 goto Done;
1572 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001573
Laurence Lundblade642282a2020-06-23 12:00:33 -07001574 /*
1575 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001576 array. The check for the end of an indefinite length array is
1577 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001578 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001579 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001580 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001581 goto Done;
1582 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001583
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001584 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001585 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001586 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1587 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001588 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001589 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301590
Laurence Lundblade642282a2020-06-23 12:00:33 -07001591 /*
1592 Breaks ending arrays/maps are always processed at the end of this
1593 function. They should never show up here.
1594 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301595 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001596 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301597 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301598 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade642282a2020-06-23 12:00:33 -07001600 /*
1601 Record the nesting level for this data item before processing any
1602 of decrementing and descending.
1603 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001604 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundblade642282a2020-06-23 12:00:33 -07001606
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001607 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001608 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001609 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001610 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001611
Laurence Lundblade93d89472020-10-03 22:30:50 -07001612 Empty indefinite length maps and arrays are descended into, but
1613 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001614
1615 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001616 encloses them so a decrement needs to be done for them too, but
1617 that is done only when all the items in them have been
1618 processed, not when they are opened with the exception of an
1619 empty map or array.
1620 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001621 QCBORError uDescendErr;
1622 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001623 pDecodedItem->uDataType,
1624 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001625 if(uDescendErr != QCBOR_SUCCESS) {
1626 /* This error is probably a traversal error and it
1627 overrides the non-traversal error. */
1628 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001629 goto Done;
1630 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001631 }
1632
Laurence Lundblade02625d42020-06-25 14:41:41 -07001633 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1634 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1635 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001636 /*
1637 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001638 - A non-aggregate like an integer or string
1639 - An empty definite length map or array
1640 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001641
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001642 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001643 definite length map/array and break detection for an indefinite
1644 length map/array. If the end of the map/array was reached, then
1645 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001646 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001647 QCBORError uAscendErr;
1648 uAscendErr = NestLevelAscender(me, true);
1649 if(uAscendErr != QCBOR_SUCCESS) {
1650 /* This error is probably a traversal error and it
1651 overrides the non-traversal error. */
1652 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001653 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001654 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301655 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001656
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001657 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001659 Tell the caller what level is next. This tells them what
1660 maps/arrays were closed out and makes it possible for them to
1661 reconstruct the tree with just the information returned in
1662 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001663 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001664 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001665 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001666 pDecodedItem->uNextNestLevel = 0;
1667 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001668 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001669 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001671Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001672 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001673}
1674
Laurence Lundblade9b334962020-08-27 10:55:53 -07001675static void ShiftTags(QCBORItem *pDecodedItem)
1676{
1677 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1678 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1679 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1680 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1681}
1682
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001683
Laurence Lundblade9b334962020-08-27 10:55:53 -07001684
Laurence Lundblade59289e52019-12-30 13:44:37 -08001685/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001686 The epoch formatted date. Turns lots of different forms of encoding
1687 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001688 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001689static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001690{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001691 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692
1693 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1694
1695 switch (pDecodedItem->uDataType) {
1696
1697 case QCBOR_TYPE_INT64:
1698 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1699 break;
1700
1701 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001702 // This only happens for CBOR type 0 > INT64_MAX so it is
1703 // always an overflow.
1704 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1705 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001706 break;
1707
1708 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001709 case QCBOR_TYPE_FLOAT:
1710#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001711 {
1712 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001713 // conversion to an int64_t to be able to detect doubles that
1714 // are too large to fit into an int64_t. A double has 52
1715 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1716 // to a double actually causes a round up which is bad and
1717 // wrong for the comparison because it will allow conversion
1718 // of doubles that can't fit into a uint64_t. To remedy this
1719 // INT64_MAX - 0x7ff is used as the cutoff point because if
1720 // that value rounds up in conversion to double it will still
1721 // be less than INT64_MAX. 0x7ff is picked because it has 11
1722 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001723 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001724 // INT64_MAX seconds is on the order of 10 billion years, and
1725 // the earth is less than 5 billion years old, so for most
1726 // uses this conversion error won't occur even though doubles
1727 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001728 //
1729 // Without the 0x7ff there is a ~30 minute range of time
1730 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001731 // where this code would go wrong. Some compilers
1732 // will generate warnings or errors without the 0x7ff
1733 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001734 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1735 pDecodedItem->val.dfnum :
1736 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001737 if(isnan(d) ||
1738 d > (double)(INT64_MAX - 0x7ff) ||
1739 d < (double)(INT64_MIN + 0x7ff)) {
1740 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001741 goto Done;
1742 }
1743 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001744 pDecodedItem->val.epochDate.fSecondsFraction =
1745 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001747#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001748
Laurence Lundbladec7114722020-08-13 05:11:40 -07001749 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001750 goto Done;
1751
Laurence Lundblade9682a532020-06-06 18:33:04 -07001752#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001753 break;
1754
1755 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001756 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001757 goto Done;
1758 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001759
Laurence Lundblade59289e52019-12-30 13:44:37 -08001760 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1761
1762Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001763 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764}
1765
1766
1767#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1768/*
1769 Decode decimal fractions and big floats.
1770
1771 When called pDecodedItem must be the array that is tagged as a big
1772 float or decimal fraction, the array that has the two members, the
1773 exponent and mantissa.
1774
1775 This will fetch and decode the exponent and mantissa and put the
1776 result back into pDecodedItem.
1777 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001778static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1780{
1781 QCBORError nReturn;
1782
1783 // --- Make sure it is an array; track nesting level of members ---
1784 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1785 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1786 goto Done;
1787 }
1788
1789 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001790 // definite length arrays, but not for indefnite. Instead remember
1791 // the nesting level the two integers must be at, which is one
1792 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001793 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1794
1795 // --- Is it a decimal fraction or a bigfloat? ---
1796 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1797 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1798
1799 // --- Get the exponent ---
1800 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001801 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001802 if(nReturn != QCBOR_SUCCESS) {
1803 goto Done;
1804 }
1805 if(exponentItem.uNestingLevel != nNestLevel) {
1806 // Array is empty or a map/array encountered when expecting an int
1807 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1808 goto Done;
1809 }
1810 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1811 // Data arriving as an unsigned int < INT64_MAX has been converted
1812 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1813 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1814 // will be too large for this to handle and thus an error that will
1815 // get handled in the next else.
1816 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1817 } else {
1818 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1819 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1820 goto Done;
1821 }
1822
1823 // --- Get the mantissa ---
1824 QCBORItem mantissaItem;
1825 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1826 if(nReturn != QCBOR_SUCCESS) {
1827 goto Done;
1828 }
1829 if(mantissaItem.uNestingLevel != nNestLevel) {
1830 // Mantissa missing or map/array encountered when expecting number
1831 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1832 goto Done;
1833 }
1834 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1835 // Data arriving as an unsigned int < INT64_MAX has been converted
1836 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1837 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1838 // will be too large for this to handle and thus an error that
1839 // will get handled in an else below.
1840 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001841 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1842 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001843 // Got a good big num mantissa
1844 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1845 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001846 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1847 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1848 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001849 } else {
1850 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1851 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1852 goto Done;
1853 }
1854
1855 // --- Check that array only has the two numbers ---
1856 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001857 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001858 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1859 goto Done;
1860 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001861 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001862
1863Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001864 return nReturn;
1865}
1866#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1867
1868
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001869static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001870{
1871 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1872 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001873 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001874 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1875 } else {
1876 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001877
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001878 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001879
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001880 return QCBOR_SUCCESS;
1881}
1882
1883
Laurence Lundblade99615302020-11-29 11:19:47 -08001884/*
1885 * Table of CBOR tags whose content is either a text string or a byte
1886 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1887 * of uQCBORtype indicates the content should be a byte string rather
1888 * than a text string
1889 */
1890struct StringTagMapEntry {
1891 uint16_t uTagNumber;
1892 uint8_t uQCBORtype;
1893};
1894
1895#define IS_BYTE_STRING_BIT 0x80
1896#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1897
1898static const struct StringTagMapEntry StringTagMap[] = {
1899 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1900 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1901 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1902 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1903 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1904 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1905 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1906 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1907 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1908 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1909 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1910};
1911
1912
1913/*
1914 * Process the CBOR tags that whose content is a byte string or a text
1915 * string and for which the string is just passed on to the caller.
1916 *
1917 * This maps the CBOR tag to the QCBOR type and checks the content
1918 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001919 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001920 * possible.
1921 *
1922 * This returns QCBOR_SUCCESS if the tag was procssed,
1923 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1924 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1925 */
1926static inline
1927QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001928{
Laurence Lundblade99615302020-11-29 11:19:47 -08001929 /* This only works on tags that were not mapped; no need for other yet */
1930 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1931 return QCBOR_ERR_UNSUPPORTED;
1932 }
1933
1934 unsigned uIndex;
1935 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1936 if(StringTagMap[uIndex].uTagNumber == uTag) {
1937 break;
1938 }
1939 }
1940
1941 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1942 if(uQCBORType == QCBOR_TYPE_NONE) {
1943 /* repurpose this error to mean, not handled here */
1944 return QCBOR_ERR_UNSUPPORTED;
1945 }
1946
1947 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1948 if(uQCBORType & IS_BYTE_STRING_BIT) {
1949 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1950 }
1951
1952 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001953 return QCBOR_ERR_BAD_OPT_TAG;
1954 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001955
Laurence Lundblade99615302020-11-29 11:19:47 -08001956 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001957 return QCBOR_SUCCESS;
1958}
1959
1960
Laurence Lundblade59289e52019-12-30 13:44:37 -08001961/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001962 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1963 * but the whole tag was not decoded. Here, the whole tags (tag number
1964 * and tag content) that are supported by QCBOR are decoded. This is a
1965 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001967static QCBORError
1968QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001969{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001970 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001971
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001972 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1973 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974 goto Done;
1975 }
1976
Laurence Lundblade99615302020-11-29 11:19:47 -08001977 /* When there are no tag numbers for the item, this exits first
1978 * thing and effectively does nothing.
1979 *
1980 * This loops over all the tag numbers accumulated for this item
1981 * trying to decode and interpret them. This stops at the end of
1982 * the list or at the first tag number that can't be interpreted by
1983 * this code. This is effectively a recursive processing of the
1984 * tags number list that handles nested tags.
1985 */
1986 while(1) {
1987 /* Don't bother to unmap tags via QCBORITem.uTags since this
1988 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
1989 */
1990 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991
Laurence Lundblade99615302020-11-29 11:19:47 -08001992 if(uTagToProcess == CBOR_TAG_INVALID16) {
1993 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001994 break;
1995
Laurence Lundblade99615302020-11-29 11:19:47 -08001996 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001997 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001998
Laurence Lundblade93d89472020-10-03 22:30:50 -07001999#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002000 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2001 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002002 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002003#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004
Laurence Lundblade99615302020-11-29 11:19:47 -08002005 } else if(uTagToProcess == CBOR_TAG_MIME ||
2006 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002007 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002008
Laurence Lundblade99615302020-11-29 11:19:47 -08002009 } else {
2010 /* See if it is a pass-through byte/text string tag; process if so */
2011 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002012
Laurence Lundblade99615302020-11-29 11:19:47 -08002013 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2014 /* It wasn't a pass-through byte/text string tag so it is
2015 * an unknown tag. This is the exit from the loop on the
2016 * first unknown tag. It is a successful exit.
2017 */
2018 uReturn = QCBOR_SUCCESS;
2019 break;
2020 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002021 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002022
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002023 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002024 /* Error exit from the loop */
2025 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002026 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002027
2028 /* A tag was successfully processed, shift it out of the list of
2029 * tags returned. This is the loop increment.
2030 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002031 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002032 }
2033
2034Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002035 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002036}
2037
2038
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002039/*
2040 Public function, see header qcbor/qcbor_decode.h file
2041 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002042QCBORError
2043QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2044{
2045 QCBORError uErr;
2046 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2047 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2049 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2050 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002051 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052}
2053
2054
2055/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002056 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002057 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002058QCBORError
2059QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2060{
2061 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2062 const UsefulInputBuf Save = pMe->InBuf;
2063
2064 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2065
2066 pMe->nesting = SaveNesting;
2067 pMe->InBuf = Save;
2068
2069 return uErr;
2070}
2071
2072
2073/*
2074 Public function, see header qcbor/qcbor_decode.h file
2075 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002076void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2077{
2078 if(pMe->uLastError != QCBOR_SUCCESS) {
2079 return;
2080 }
2081
2082 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2083}
2084
2085
2086/*
2087 Public function, see header qcbor/qcbor_decode.h file
2088 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002089QCBORError
2090QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2091 QCBORItem *pDecodedItem,
2092 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002093{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002094 QCBORError nReturn;
2095
2096 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2097 if(nReturn != QCBOR_SUCCESS) {
2098 return nReturn;
2099 }
2100
2101 if(pTags != NULL) {
2102 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002103 // Reverse the order because pTags is reverse of
2104 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002105 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2106 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002107 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002108 }
2109 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2110 return QCBOR_ERR_TOO_MANY_TAGS;
2111 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002112 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002113 pTags->uNumUsed++;
2114 }
2115 }
2116
2117 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002118}
2119
2120
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002121/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302122 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302123 next one down. If a layer has no work to do for a particular item
2124 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002125
Laurence Lundblade59289e52019-12-30 13:44:37 -08002126 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2127 tagged data items, turning them into the local C representation.
2128 For the most simple it is just associating a QCBOR_TYPE with the data. For
2129 the complex ones that an aggregate of data items, there is some further
2130 decoding and a little bit of recursion.
2131
2132 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302133 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302134 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002135 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002136
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302137 - GetNext_MapEntry -- This handles the combining of two
2138 items, the label and the data, that make up a map entry.
2139 It only does work on maps. It combines the label and data
2140 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002141
Laurence Lundblade59289e52019-12-30 13:44:37 -08002142 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2143 tags into bit flags associated with the data item. No actual decoding
2144 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002145
Laurence Lundblade59289e52019-12-30 13:44:37 -08002146 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302147 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302148 string allocater to create contiguous space for the item. It
2149 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002150
Laurence Lundblade59289e52019-12-30 13:44:37 -08002151 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2152 atomic data item has a "major type", an integer "argument" and optionally
2153 some content. For text and byte strings, the content is the bytes
2154 that make up the string. These are the smallest data items that are
2155 considered to be well-formed. The content may also be other data items in
2156 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002157
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002158 Roughly this takes 300 bytes of stack for vars. Need to
2159 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002160
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302161 */
2162
2163
2164/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002165 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002166 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002167bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002168 const QCBORItem *pItem,
2169 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002170{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002171 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2172 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002173 break;
2174 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002175 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002176 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002177 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002179
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002180 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002181}
2182
2183
2184/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002185 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002186 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002187QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002188{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002189 QCBORError uReturn = me->uLastError;
2190
2191 if(uReturn != QCBOR_SUCCESS) {
2192 goto Done;
2193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002195 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002196 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002197 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002198 goto Done;
2199 }
2200
2201 // Error out if not all the bytes are consumed
2202 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002203 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002205
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002206Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002207#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302208 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002209 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002210 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002211#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002212
Laurence Lundblade085d7952020-07-24 10:26:30 -07002213 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002214}
2215
2216
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002217/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002218 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002219*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002220// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002221uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2222 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002223 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002224{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002225 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2226 return CBOR_TAG_INVALID64;
2227 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002228 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2229 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002230 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002231 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002232 }
2233}
2234
Laurence Lundblade9b334962020-08-27 10:55:53 -07002235/*
2236 Public function, see header qcbor/qcbor_decode.h file
2237*/
2238uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2239 uint32_t uIndex)
2240{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002241 if(pMe->uLastError != QCBOR_SUCCESS) {
2242 return CBOR_TAG_INVALID64;
2243 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002244 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2245 return CBOR_TAG_INVALID64;
2246 } else {
2247 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2248 }
2249}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002250
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002251/*
2252
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002253Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002254
Laurence Lundbladeee851742020-01-08 08:37:05 -08002255 - Hit end of input before it was expected while decoding type and
2256 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002258 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002259
Laurence Lundbladeee851742020-01-08 08:37:05 -08002260 - Hit end of input while decoding a text or byte string
2261 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002262
Laurence Lundbladeee851742020-01-08 08:37:05 -08002263 - Encountered conflicting tags -- e.g., an item is tagged both a date
2264 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002265
Laurence Lundbladeee851742020-01-08 08:37:05 -08002266 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002267 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002268
Laurence Lundbladeee851742020-01-08 08:37:05 -08002269 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002270 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271
Laurence Lundbladeee851742020-01-08 08:37:05 -08002272 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2273 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275 - The type of a map label is not a string or int
2276 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002277
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002278 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002280 */
2281
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002282
2283
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002284#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002285
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002286/* ===========================================================================
2287 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002288
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002289 This implements a simple sting allocator for indefinite length
2290 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2291 implements the function type QCBORStringAllocate and allows easy
2292 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002293
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002294 This particular allocator is built-in for convenience. The caller
2295 can implement their own. All of this following code will get
2296 dead-stripped if QCBORDecode_SetMemPool() is not called.
2297
2298 This is a very primitive memory allocator. It does not track
2299 individual allocations, only a high-water mark. A free or
2300 reallocation must be of the last chunk allocated.
2301
2302 The size of the pool and offset to free memory are packed into the
2303 first 8 bytes of the memory pool so we don't have to keep them in
2304 the decode context. Since the address of the pool may not be
2305 aligned, they have to be packed and unpacked as if they were
2306 serialized data of the wire or such.
2307
2308 The sizes packed in are uint32_t to be the same on all CPU types
2309 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002310 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002311
2312
Laurence Lundbladeee851742020-01-08 08:37:05 -08002313static inline int
2314MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002315{
2316 // Use of UsefulInputBuf is overkill, but it is convenient.
2317 UsefulInputBuf UIB;
2318
Laurence Lundbladeee851742020-01-08 08:37:05 -08002319 // Just assume the size here. It was checked during SetUp so
2320 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002321 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002322 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2323 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2324 return UsefulInputBuf_GetError(&UIB);
2325}
2326
2327
Laurence Lundbladeee851742020-01-08 08:37:05 -08002328static inline int
2329MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002330{
2331 // Use of UsefulOutBuf is overkill, but convenient. The
2332 // length check performed here is useful.
2333 UsefulOutBuf UOB;
2334
2335 UsefulOutBuf_Init(&UOB, Pool);
2336 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2337 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2338 return UsefulOutBuf_GetError(&UOB);
2339}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002340
2341
2342/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002343 Internal function for an allocation, reallocation free and destuct.
2344
2345 Having only one function rather than one each per mode saves space in
2346 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002347
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002348 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2349 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002350static UsefulBuf
2351MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002352{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002353 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002354
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002355 uint32_t uPoolSize;
2356 uint32_t uFreeOffset;
2357
2358 if(uNewSize > UINT32_MAX) {
2359 // This allocator is only good up to 4GB. This check should
2360 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2361 goto Done;
2362 }
2363 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2364
2365 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2366 goto Done;
2367 }
2368
2369 if(uNewSize) {
2370 if(pMem) {
2371 // REALLOCATION MODE
2372 // Calculate pointer to the end of the memory pool. It is
2373 // assumed that pPool + uPoolSize won't wrap around by
2374 // assuming the caller won't pass a pool buffer in that is
2375 // not in legitimate memory space.
2376 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2377
2378 // Check that the pointer for reallocation is in the range of the
2379 // pool. This also makes sure that pointer math further down
2380 // doesn't wrap under or over.
2381 if(pMem >= pPool && pMem < pPoolEnd) {
2382 // Offset to start of chunk for reallocation. This won't
2383 // wrap under because of check that pMem >= pPool. Cast
2384 // is safe because the pool is always less than UINT32_MAX
2385 // because of check in QCBORDecode_SetMemPool().
2386 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2387
2388 // Check to see if the allocation will fit. uPoolSize -
2389 // uMemOffset will not wrap under because of check that
2390 // pMem is in the range of the uPoolSize by check above.
2391 if(uNewSize <= uPoolSize - uMemOffset) {
2392 ReturnValue.ptr = pMem;
2393 ReturnValue.len = uNewSize;
2394
2395 // Addition won't wrap around over because uNewSize was
2396 // checked to be sure it is less than the pool size.
2397 uFreeOffset = uMemOffset + uNewSize32;
2398 }
2399 }
2400 } else {
2401 // ALLOCATION MODE
2402 // uPoolSize - uFreeOffset will not underflow because this
2403 // pool implementation makes sure uFreeOffset is always
2404 // smaller than uPoolSize through this check here and
2405 // reallocation case.
2406 if(uNewSize <= uPoolSize - uFreeOffset) {
2407 ReturnValue.len = uNewSize;
2408 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002409 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002410 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002411 }
2412 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002413 if(pMem) {
2414 // FREE MODE
2415 // Cast is safe because of limit on pool size in
2416 // QCBORDecode_SetMemPool()
2417 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2418 } else {
2419 // DESTRUCT MODE
2420 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002421 }
2422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002424 UsefulBuf Pool = {pPool, uPoolSize};
2425 MemPool_Pack(Pool, uFreeOffset);
2426
2427Done:
2428 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002429}
2430
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002431
Laurence Lundbladef6531662018-12-04 10:42:22 +09002432/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002433 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002434 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002435QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2436 UsefulBuf Pool,
2437 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002438{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002439 // The pool size and free mem offset are packed into the beginning
2440 // of the pool memory. This compile time check make sure the
2441 // constant in the header is correct. This check should optimize
2442 // down to nothing.
2443 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002444 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002446
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002447 // The pool size and free offset packed in to the beginning of pool
2448 // memory are only 32-bits. This check will optimize out on 32-bit
2449 // machines.
2450 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002451 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002452 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002453
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002454 // This checks that the pool buffer given is big enough.
2455 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002456 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002457 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002458
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002459 pMe->StringAllocator.pfAllocator = MemPool_Function;
2460 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2461 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002462
Laurence Lundblade30816f22018-11-10 13:40:22 +07002463 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002464}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002465#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002466
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002467
2468
Laurence Lundblade9b334962020-08-27 10:55:53 -07002469static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2470{
2471 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2472}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002473
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002474
2475/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002476 Consume an entire map or array (and do next to
2477 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002479static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480ConsumeItem(QCBORDecodeContext *pMe,
2481 const QCBORItem *pItemToConsume,
2482 uint_fast8_t *puNextNestLevel)
2483{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002484 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002485 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002486
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002487 // If it is a map or array, this will tell if it is empty.
2488 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2489
2490 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2491 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002492
Laurence Lundblade1341c592020-04-11 14:19:05 -07002493 /* This works for definite and indefinite length
2494 * maps and arrays by using the nesting level
2495 */
2496 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002497 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002498 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002499 goto Done;
2500 }
2501 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002503 *puNextNestLevel = Item.uNextNestLevel;
2504
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002505 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002506
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002508 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002509 /* Just pass the nesting level through */
2510 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2511
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002512 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002513 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002514
2515Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002516 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002517}
2518
2519
Laurence Lundblade1341c592020-04-11 14:19:05 -07002520/* Return true if the labels in Item1 and Item2 are the same.
2521 Works only for integer and string labels. Returns false
2522 for any other type. */
2523static inline bool
2524MatchLabel(QCBORItem Item1, QCBORItem Item2)
2525{
2526 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2527 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2528 return true;
2529 }
2530 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002531 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002532 return true;
2533 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002534 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002535 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2536 return true;
2537 }
2538 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2539 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2540 return true;
2541 }
2542 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002543
Laurence Lundblade1341c592020-04-11 14:19:05 -07002544 /* Other label types are never matched */
2545 return false;
2546}
2547
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002548
2549/*
2550 Returns true if Item1 and Item2 are the same type
2551 or if either are of QCBOR_TYPE_ANY.
2552 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553static inline bool
2554MatchType(QCBORItem Item1, QCBORItem Item2)
2555{
2556 if(Item1.uDataType == Item2.uDataType) {
2557 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002558 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002559 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002560 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002561 return true;
2562 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002563 return false;
2564}
2565
2566
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002567/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002568 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002569
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002570 @param[in] pMe The decode context to search.
2571 @param[in,out] pItemArray The items to search for and the items found.
2572 @param[out] puOffset Byte offset of last item matched.
2573 @param[in] pCBContext Context for the not-found item call back.
2574 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002575
2576 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2577
Laurence Lundblade93d89472020-10-03 22:30:50 -07002578 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2579 were found for one of the labels being
2580 search for. This duplicate detection is
2581 only performed for items in pItemArray,
2582 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002583
Laurence Lundblade93d89472020-10-03 22:30:50 -07002584 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2585 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002586
2587 @retval Also errors returned by QCBORDecode_GetNext().
2588
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002589 On input pItemArray contains a list of labels and data types
2590 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002591
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002592 On output the fully retrieved items are filled in with
2593 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002594
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002595 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002596
2597 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002598 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002599static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002600MapSearch(QCBORDecodeContext *pMe,
2601 QCBORItem *pItemArray,
2602 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002603 void *pCBContext,
2604 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002605{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002606 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002607 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002608
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002609 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002610 uReturn = pMe->uLastError;
2611 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002612 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002613
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002614 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002615 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2616 /* QCBOR_TYPE_NONE as first item indicates just looking
2617 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002618 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2619 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002620 }
2621
Laurence Lundblade085d7952020-07-24 10:26:30 -07002622 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2623 // It is an empty bounded array or map
2624 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2625 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002626 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002627 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002628 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002629 // Nothing is ever found in an empty array or map. All items
2630 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002631 uReturn = QCBOR_SUCCESS;
2632 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002633 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002634 }
2635
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002636 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002637 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2638
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002639 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002640 UsefulInputBuf_Seek(&(pMe->InBuf),
2641 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002642
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002643 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002644 Loop over all the items in the map or array. Each item
2645 could be a map or array, but label matching is only at
2646 the main level. This handles definite and indefinite
2647 length maps and arrays. The only reason this is ever
2648 called on arrays is to find their end position.
2649
2650 This will always run over all items in order to do
2651 duplicate detection.
2652
2653 This will exit with failure if it encounters an
2654 unrecoverable error, but continue on for recoverable
2655 errors.
2656
2657 If a recoverable error occurs on a matched item, then
2658 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002659 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002660 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002661 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002662 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002663 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002664 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002665
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002666 /* Get the item */
2667 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002668 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2669 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002670 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002671 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002672 goto Done;
2673 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002674 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002675 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002676 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002677 goto Done;
2678 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002679
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002680 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002681 bool bMatched = false;
2682 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2683 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002684 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002685 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2686 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002688 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002689 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002690 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002691 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002692 goto Done;
2693 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002694
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002695 if(uResult != QCBOR_SUCCESS) {
2696 uReturn = uResult;
2697 goto Done;
2698 }
2699
Laurence Lundblade1341c592020-04-11 14:19:05 -07002700 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002701 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002702 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002703 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002704 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002706 bMatched = true;
2707 }
2708 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002709
2710
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002711 if(!bMatched && pfCallback != NULL) {
2712 /*
2713 Call the callback on unmatched labels.
2714 (It is tempting to do duplicate detection here, but that would
2715 require dynamic memory allocation because the number of labels
2716 that might be encountered is unbounded.)
2717 */
2718 uReturn = (*pfCallback)(pCBContext, &Item);
2719 if(uReturn != QCBOR_SUCCESS) {
2720 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 }
2722 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002723
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002724 /*
2725 Consume the item whether matched or not. This
2726 does the work of traversing maps and array and
2727 everything in them. In this loop only the
2728 items at the current nesting level are examined
2729 to match the labels.
2730 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002731 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002732 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002733 goto Done;
2734 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002735
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002736 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002737
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002738 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002739
2740 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002741
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002742 // Check here makes sure that this won't accidentally be
2743 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002744 // QCBOR_MAX_DECODE_INPUT_SIZE.
2745 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2746 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2747 goto Done;
2748 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002749 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2750 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002751
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002752 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002753 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2754
2755 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002756 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002757 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002758 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002759 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2760 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002761 }
2762 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002763
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002764 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002765}
2766
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002767
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002768/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002769 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002770*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002771void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2772 int64_t nLabel,
2773 uint8_t uQcborType,
2774 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002776 if(pMe->uLastError != QCBOR_SUCCESS) {
2777 return;
2778 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002779
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002780 QCBORItem OneItemSeach[2];
2781 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2782 OneItemSeach[0].label.int64 = nLabel;
2783 OneItemSeach[0].uDataType = uQcborType;
2784 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002785
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002786 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002787
2788 *pItem = OneItemSeach[0];
2789
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002790 if(uReturn != QCBOR_SUCCESS) {
2791 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002792 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002793 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002794 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002795 }
2796
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002797 Done:
2798 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002799}
2800
2801
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002802/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002803 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002804*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002805void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2806 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002807 uint8_t uQcborType,
2808 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002810 if(pMe->uLastError != QCBOR_SUCCESS) {
2811 return;
2812 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002813
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002814 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002815 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2816 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2817 OneItemSeach[0].uDataType = uQcborType;
2818 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002819
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002820 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2821 if(uReturn != QCBOR_SUCCESS) {
2822 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002823 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002824 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002825 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002826 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002827 }
2828
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002829 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002830
2831Done:
2832 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002833}
2834
2835
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002836
Laurence Lundblade93d89472020-10-03 22:30:50 -07002837static QCBORError
2838CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002839{
2840 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2841 if(uDataType == puTypeList[i]) {
2842 return QCBOR_SUCCESS;
2843 }
2844 }
2845 return QCBOR_ERR_UNEXPECTED_TYPE;
2846}
2847
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002848
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002849/**
2850 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002851 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002852
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002853 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2854 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002855
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002856 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2857 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002858 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002859static QCBORError
2860CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002861{
2862 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2863 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2864 /* There are tags that QCBOR couldn't process on this item and
2865 the caller has told us there should not be. */
2866 return QCBOR_ERR_UNEXPECTED_TYPE;
2867 }
2868
2869 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2870 const int nItemType = pItem->uDataType;
2871
2872 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2873 // Must match the tag and only the tag
2874 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2875 }
2876
2877 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2878 if(uReturn == QCBOR_SUCCESS) {
2879 return QCBOR_SUCCESS;
2880 }
2881
2882 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2883 /* Must match the content type and only the content type.
2884 There was no match just above so it is a fail. */
2885 return QCBOR_ERR_UNEXPECTED_TYPE;
2886 }
2887
2888 /* If here it can match either the tag or the content
2889 and it hasn't matched the content, so the end
2890 result is whether it matches the tag. This is
2891 also the case that the CBOR standard discourages. */
2892
2893 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2894}
2895
Laurence Lundblade9b334962020-08-27 10:55:53 -07002896
Laurence Lundblade9b334962020-08-27 10:55:53 -07002897
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002898// This could be semi-private if need be
2899static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002900void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2901 int64_t nLabel,
2902 TagSpecification TagSpec,
2903 QCBORItem *pItem)
2904{
2905 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2906 if(pMe->uLastError != QCBOR_SUCCESS) {
2907 return;
2908 }
2909
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002910 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002911}
2912
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002913
2914// This could be semi-private if need be
2915static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002916void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2917 const char *szLabel,
2918 TagSpecification TagSpec,
2919 QCBORItem *pItem)
2920{
2921 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2922 if(pMe->uLastError != QCBOR_SUCCESS) {
2923 return;
2924 }
2925
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002926 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002927}
2928
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002929// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002930void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2931 int64_t nLabel,
2932 TagSpecification TagSpec,
2933 UsefulBufC *pString)
2934{
2935 QCBORItem Item;
2936 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2937 if(pMe->uLastError == QCBOR_SUCCESS) {
2938 *pString = Item.val.string;
2939 }
2940}
2941
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002942// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002943void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2944 const char * szLabel,
2945 TagSpecification TagSpec,
2946 UsefulBufC *pString)
2947{
2948 QCBORItem Item;
2949 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2950 if(pMe->uLastError == QCBOR_SUCCESS) {
2951 *pString = Item.val.string;
2952 }
2953}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002954
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002955/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002956 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002957*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002958void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002959{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002960 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2961 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002962}
2963
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002964/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002965 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002966*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002967void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2968 QCBORItem *pItemList,
2969 void *pCallbackCtx,
2970 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002971{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002972 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2973 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002974}
2975
2976
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002977/**
2978 * @brief Search for a map/array by label and enter it
2979 *
2980 * @param[in] pMe The decode context.
2981 * @param[in] pSearch The map/array to search for.
2982 *
2983 * @c pSearch is expected to contain one item of type map or array
2984 * with the label specified. The current bounded map will be searched for
2985 * this and if found will be entered.
2986 *
2987 * If the label is not found, or the item found is not a map or array,
2988 * the error state is set.
2989 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002990static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002991{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002992 // The first item in pSearch is the one that is to be
2993 // entered. It should be the only one filled in. Any other
2994 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002995 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002996 return;
2997 }
2998
2999 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003000 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003001 if(pMe->uLastError != QCBOR_SUCCESS) {
3002 return;
3003 }
3004
Laurence Lundblade9b334962020-08-27 10:55:53 -07003005 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003006 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003007 return;
3008 }
3009
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003010 /*
3011 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3012 * next item for the pre-order traversal cursor to be the map/array
3013 * found by MapSearch(). The next few lines of code force the
3014 * cursor to that.
3015 *
3016 * There is no need to retain the old cursor because
3017 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3018 * beginning of the map/array being entered.
3019 *
3020 * The cursor is forced by: 1) setting the input buffer position to
3021 * the item offset found by MapSearch(), 2) setting the map/array
3022 * counter to the total in the map/array, 3) setting the nesting
3023 * level. Setting the map/array counter to the total is not
3024 * strictly correct, but this is OK because this cursor only needs
3025 * to be used to get one item and MapSearch() has already found it
3026 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003027 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003028 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003029
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003030 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3031
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003032 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003033
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003034 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003035}
3036
3037
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003038/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003039 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003040*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003041void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003042{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003043 QCBORItem OneItemSeach[2];
3044 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3045 OneItemSeach[0].label.int64 = nLabel;
3046 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3047 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003048
Laurence Lundblade9b334962020-08-27 10:55:53 -07003049 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003050 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003051}
3052
3053
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003054/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003055 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003056*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003057void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003058{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003059 QCBORItem OneItemSeach[2];
3060 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3061 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3062 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3063 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003064
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003065 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003066}
3067
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003068/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003069 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003070*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003071void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003072{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003073 QCBORItem OneItemSeach[2];
3074 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3075 OneItemSeach[0].label.int64 = nLabel;
3076 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3077 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003078
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003079 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003080}
3081
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003083 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003084*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003085void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3086{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003087 QCBORItem OneItemSeach[2];
3088 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3089 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3090 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3091 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003093 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003094}
3095
3096
Laurence Lundblade02625d42020-06-25 14:41:41 -07003097// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003098void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003099{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003100 QCBORError uErr;
3101
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003102 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003103 if(pMe->uLastError != QCBOR_SUCCESS) {
3104 // Already in error state; do nothing.
3105 return;
3106 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003107
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003108 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003109 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003110 uErr = QCBORDecode_GetNext(pMe, &Item);
3111 if(uErr != QCBOR_SUCCESS) {
3112 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003113 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003114 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003115 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3116 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003117 }
3118
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003119 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003120
3121
Laurence Lundbladef0499502020-08-01 11:55:57 -07003122 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003123 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003124 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3125 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003126 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003127 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3128 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003129 // Special case to increment nesting level for zero-length maps
3130 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003131 DecodeNesting_Descend(&(pMe->nesting), uType);
3132 }
3133
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003134 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003135
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003136 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3137 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003138
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003139 if(pItem != NULL) {
3140 *pItem = Item;
3141 }
3142
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003143Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003144 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003145}
3146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147
3148/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003149 This is the common work for exiting a level that is a bounded map,
3150 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003151
3152 One chunk of work is to set up the pre-order traversal so it is at
3153 the item just after the bounded map, array or bstr that is being
3154 exited. This is somewhat complex.
3155
3156 The other work is to level-up the bounded mode to next higest bounded
3157 mode or the top level if there isn't one.
3158 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003159static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003160ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003161{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003162 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003163
Laurence Lundblade02625d42020-06-25 14:41:41 -07003164 /*
3165 First the pre-order-traversal byte offset is positioned to the
3166 item just after the bounded mode item that was just consumed.
3167 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003168 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3169
Laurence Lundblade02625d42020-06-25 14:41:41 -07003170 /*
3171 Next, set the current nesting level to one above the bounded level
3172 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003173
Laurence Lundblade02625d42020-06-25 14:41:41 -07003174 DecodeNesting_CheckBoundedType() is always called before this and
3175 makes sure pCurrentBounded is valid.
3176 */
3177 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3178
3179 /*
3180 This does the complex work of leveling up the pre-order traversal
3181 when the end of a map or array or another bounded level is
3182 reached. It may do nothing, or ascend all the way to the top
3183 level.
3184 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003185 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003186 if(uErr != QCBOR_SUCCESS) {
3187 goto Done;
3188 }
3189
Laurence Lundblade02625d42020-06-25 14:41:41 -07003190 /*
3191 This makes the next highest bounded level the current bounded
3192 level. If there is no next highest level, then no bounded mode is
3193 in effect.
3194 */
3195 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003196
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003197 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003198
3199Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003200 return uErr;
3201}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003202
Laurence Lundblade02625d42020-06-25 14:41:41 -07003203
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003204// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003205void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003206{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003207 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003209 return;
3210 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003211
Laurence Lundblade02625d42020-06-25 14:41:41 -07003212 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003213
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003214 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003215 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003216 goto Done;
3217 }
3218
Laurence Lundblade02625d42020-06-25 14:41:41 -07003219 /*
3220 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003221 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003222 from previous map search, then do a dummy search.
3223 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003224 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003225 QCBORItem Dummy;
3226 Dummy.uLabelType = QCBOR_TYPE_NONE;
3227 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3228 if(uErr != QCBOR_SUCCESS) {
3229 goto Done;
3230 }
3231 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003232
Laurence Lundblade02625d42020-06-25 14:41:41 -07003233 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003234
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003235Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003236 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003237}
3238
3239
Laurence Lundblade1341c592020-04-11 14:19:05 -07003240
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003241static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003242 const QCBORItem *pItem,
3243 uint8_t uTagRequirement,
3244 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003245{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003246 if(pBstr) {
3247 *pBstr = NULLUsefulBufC;
3248 }
3249
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003250 if(pMe->uLastError != QCBOR_SUCCESS) {
3251 // Already in error state; do nothing.
3252 return pMe->uLastError;
3253 }
3254
3255 QCBORError uError = QCBOR_SUCCESS;
3256
3257 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3258 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3259 goto Done;;
3260 }
3261
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003262 const TagSpecification TagSpec =
3263 {
3264 uTagRequirement,
3265 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3266 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3267 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003268
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003269 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003270 if(uError != QCBOR_SUCCESS) {
3271 goto Done;
3272 }
3273
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003274 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003275 // Reverse the decrement done by GetNext() for the bstr so the
3276 // increment in NestLevelAscender() called by ExitBoundedLevel()
3277 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003278 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003279 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003280
3281 if(pBstr) {
3282 *pBstr = pItem->val.string;
3283 }
3284
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003285 // This saves the current length of the UsefulInputBuf and then
3286 // narrows the UsefulInputBuf to start and length of the wrapped
3287 // CBOR that is being entered.
3288 //
3289 // This makes sure the length is less than
3290 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3291 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3292 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3293 // the casts safe. uEndOfBstr will always be less than
3294 // uPreviousLength because of the way UsefulInputBuf works so there
3295 // is no need to check it. There is also a range check in the
3296 // seek.
3297 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003298 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003299 // amount to much code.
3300 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3301 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003302 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003303 goto Done;
3304 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003305 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003306 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003307 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003308
Laurence Lundblade02625d42020-06-25 14:41:41 -07003309 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003310 (uint32_t)uPreviousLength,
3311 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003312Done:
3313 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003314}
3315
3316
Laurence Lundblade02625d42020-06-25 14:41:41 -07003317/*
3318 Public function, see header qcbor/qcbor_decode.h file
3319 */
3320void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003321 uint8_t uTagRequirement,
3322 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003323{
3324 if(pMe->uLastError != QCBOR_SUCCESS) {
3325 // Already in error state; do nothing.
3326 return;
3327 }
3328
3329 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003330 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003331 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3332 if(pMe->uLastError != QCBOR_SUCCESS) {
3333 return;
3334 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003335
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003336 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003337 &Item,
3338 uTagRequirement,
3339 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003340}
3341
3342
Laurence Lundblade02625d42020-06-25 14:41:41 -07003343/*
3344 Public function, see header qcbor/qcbor_decode.h file
3345 */
3346void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003348 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003349 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003350{
3351 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003352 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003353
Laurence Lundblade93d89472020-10-03 22:30:50 -07003354 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3355 &Item,
3356 uTagRequirement,
3357 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003358}
3359
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003360
Laurence Lundblade02625d42020-06-25 14:41:41 -07003361/*
3362 Public function, see header qcbor/qcbor_decode.h file
3363 */
3364void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003365 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003366 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003367 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003368{
3369 QCBORItem Item;
3370 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3371
Laurence Lundblade93d89472020-10-03 22:30:50 -07003372 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3373 &Item,
3374 uTagRequirement,
3375 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003376}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003377
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003378
Laurence Lundblade02625d42020-06-25 14:41:41 -07003379/*
3380 Public function, see header qcbor/qcbor_decode.h file
3381 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003382void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003383{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003384 if(pMe->uLastError != QCBOR_SUCCESS) {
3385 // Already in error state; do nothing.
3386 return;
3387 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003388
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003389 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003390 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003391 return;
3392 }
3393
3394 /*
3395 Reset the length of the UsefulInputBuf to what it was before
3396 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003397 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003398 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003399 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003400
3401
Laurence Lundblade02625d42020-06-25 14:41:41 -07003402 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003403 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003404}
3405
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003406
Laurence Lundbladee6430642020-03-14 21:15:44 -07003407
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003408
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003409
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003410
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003411
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003412
Laurence Lundblade93d89472020-10-03 22:30:50 -07003413static QCBORError
3414InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003415{
3416 switch(pItem->uDataType) {
3417 case QCBOR_TYPE_TRUE:
3418 *pBool = true;
3419 return QCBOR_SUCCESS;
3420 break;
3421
3422 case QCBOR_TYPE_FALSE:
3423 *pBool = false;
3424 return QCBOR_SUCCESS;
3425 break;
3426
3427 default:
3428 return QCBOR_ERR_UNEXPECTED_TYPE;
3429 break;
3430 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003431 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003432}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003433
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003434
Laurence Lundblade9b334962020-08-27 10:55:53 -07003435
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003436/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003437 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003438*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003439void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003440{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003441 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003442 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443 return;
3444 }
3445
Laurence Lundbladec4537442020-04-14 18:53:22 -07003446 QCBORError nError;
3447 QCBORItem Item;
3448
3449 nError = QCBORDecode_GetNext(pMe, &Item);
3450 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003451 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003452 return;
3453 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003454 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003455}
3456
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003457
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003458/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003459 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003460*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003461void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003462{
3463 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003464 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003465
Laurence Lundblade9b334962020-08-27 10:55:53 -07003466 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003467}
3468
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003469
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003470/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003471 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003472*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003473void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3474{
3475 QCBORItem Item;
3476 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3477
Laurence Lundblade9b334962020-08-27 10:55:53 -07003478 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003479}
3480
3481
3482
Laurence Lundbladec7114722020-08-13 05:11:40 -07003483
3484static void ProcessEpochDate(QCBORDecodeContext *pMe,
3485 QCBORItem *pItem,
3486 uint8_t uTagRequirement,
3487 int64_t *pnTime)
3488{
3489 if(pMe->uLastError != QCBOR_SUCCESS) {
3490 // Already in error state, do nothing
3491 return;
3492 }
3493
3494 QCBORError uErr;
3495
3496 const TagSpecification TagSpec =
3497 {
3498 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003499 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3500 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003501 };
3502
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003503 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003504 if(uErr != QCBOR_SUCCESS) {
3505 goto Done;
3506 }
3507
3508 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3509 uErr = DecodeDateEpoch(pItem);
3510 if(uErr != QCBOR_SUCCESS) {
3511 goto Done;
3512 }
3513 }
3514
Laurence Lundblade9b334962020-08-27 10:55:53 -07003515 // Save the tags in the last item's tags in the decode context
3516 // for QCBORDecode_GetNthTagOfLast()
3517 CopyTags(pMe, pItem);
3518
Laurence Lundbladec7114722020-08-13 05:11:40 -07003519 *pnTime = pItem->val.epochDate.nSeconds;
3520
3521Done:
3522 pMe->uLastError = (uint8_t)uErr;
3523}
3524
3525
3526void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003527 uint8_t uTagRequirement,
3528 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003529{
3530 if(pMe->uLastError != QCBOR_SUCCESS) {
3531 // Already in error state, do nothing
3532 return;
3533 }
3534
3535 QCBORItem Item;
3536 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3537
3538 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3539}
3540
3541
3542void
3543QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3544 int64_t nLabel,
3545 uint8_t uTagRequirement,
3546 int64_t *pnTime)
3547{
3548 QCBORItem Item;
3549 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3550 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3551}
3552
3553
3554void
3555QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3556 const char *szLabel,
3557 uint8_t uTagRequirement,
3558 int64_t *pnTime)
3559{
3560 QCBORItem Item;
3561 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3562 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3563}
3564
3565
3566
3567
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003568void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3569 TagSpecification TagSpec,
3570 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003571{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003572 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003573 // Already in error state, do nothing
3574 return;
3575 }
3576
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003577 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003578 QCBORItem Item;
3579
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003580 uError = QCBORDecode_GetNext(pMe, &Item);
3581 if(uError != QCBOR_SUCCESS) {
3582 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003583 return;
3584 }
3585
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003586 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003587
3588 if(pMe->uLastError == QCBOR_SUCCESS) {
3589 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003590 } else {
3591 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003592 }
3593}
3594
Laurence Lundbladec4537442020-04-14 18:53:22 -07003595
3596
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003597
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003598static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003599 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003600 UsefulBufC *pValue,
3601 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003602{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003603 const TagSpecification TagSpec =
3604 {
3605 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003606 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3607 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003608 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003609
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003610 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003611 if(uErr != QCBOR_SUCCESS) {
3612 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003613 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003614
3615 *pValue = pItem->val.string;
3616
3617 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3618 *pbIsNegative = false;
3619 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3620 *pbIsNegative = true;
3621 }
3622
3623 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003624}
3625
3626
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003627/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003628 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003629 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003630void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3631 uint8_t uTagRequirement,
3632 UsefulBufC *pValue,
3633 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003634{
3635 if(pMe->uLastError != QCBOR_SUCCESS) {
3636 // Already in error state, do nothing
3637 return;
3638 }
3639
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003640 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003641 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3642 if(uError != QCBOR_SUCCESS) {
3643 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003644 return;
3645 }
3646
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003647 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003648}
3649
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003650
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003651/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003652 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003653*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003654void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3655 int64_t nLabel,
3656 uint8_t uTagRequirement,
3657 UsefulBufC *pValue,
3658 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003659{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003660 QCBORItem Item;
3661 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003662 if(pMe->uLastError != QCBOR_SUCCESS) {
3663 return;
3664 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003665
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003666 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003667}
3668
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003669
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003670/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003671 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003672*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003673void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3674 const char *szLabel,
3675 uint8_t uTagRequirement,
3676 UsefulBufC *pValue,
3677 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003678{
3679 QCBORItem Item;
3680 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003681 if(pMe->uLastError != QCBOR_SUCCESS) {
3682 return;
3683 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003684
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003685 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003686}
3687
3688
3689
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003690
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003691// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003692QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3693 const QCBORItem *pItem,
3694 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003695 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003696{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003697 const TagSpecification TagSpecText =
3698 {
3699 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003700 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3701 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003702 };
3703 const TagSpecification TagSpecBinary =
3704 {
3705 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003706 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3707 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003708 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003709
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003710 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003711
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003712 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003713 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003714 if(pbIsTag257 != NULL) {
3715 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003716 }
3717 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003718 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003719 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003720 if(pbIsTag257 != NULL) {
3721 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003722 }
3723 uReturn = QCBOR_SUCCESS;
3724
3725 } else {
3726 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3727 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003728
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003729 return uReturn;
3730}
3731
Laurence Lundblade93d89472020-10-03 22:30:50 -07003732// Improvement: add methods for wrapped CBOR, a simple alternate
3733// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003734
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003735
3736
3737
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003738#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003740typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003741
3742
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003743// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003744static QCBORError
3745Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003747 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003748
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003749 if(uResult != 0) {
3750 /* This loop will run a maximum of 19 times because
3751 * UINT64_MAX < 10 ^^ 19. More than that will cause
3752 * exit with the overflow error
3753 */
3754 for(; nExponent > 0; nExponent--) {
3755 if(uResult > UINT64_MAX / 10) {
3756 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3757 }
3758 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003759 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003760
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003761 for(; nExponent < 0; nExponent++) {
3762 uResult = uResult / 10;
3763 if(uResult == 0) {
3764 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3765 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003766 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003767 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003768 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003769
3770 *puResult = uResult;
3771
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003772 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003773}
3774
3775
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003776// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003777static QCBORError
3778Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003779{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003780 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003781
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003782 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003784 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003785 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003786 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003787 */
3788 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003789 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003790 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003791 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003792 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003793 nExponent--;
3794 }
3795
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003797 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003798 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3799 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003800 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003801 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003802 }
3803
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003804 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003805
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003806 return QCBOR_SUCCESS;
3807}
3808
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003809
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003810/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003811 Compute value with signed mantissa and signed result. Works with
3812 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003813 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003814static inline QCBORError ExponentiateNN(int64_t nMantissa,
3815 int64_t nExponent,
3816 int64_t *pnResult,
3817 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003818{
3819 uint64_t uResult;
3820
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003821 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003822 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003823 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3824
3825 // Do the exponentiation of the positive mantissa
3826 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3827 if(uReturn) {
3828 return uReturn;
3829 }
3830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003831
Laurence Lundblade983500d2020-05-14 11:49:34 -07003832 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3833 of INT64_MIN. This assumes two's compliment representation where
3834 INT64_MIN is one increment farther from 0 than INT64_MAX.
3835 Trying to write -INT64_MIN doesn't work to get this because the
3836 compiler tries to work with an int64_t which can't represent
3837 -INT64_MIN.
3838 */
3839 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3840
3841 // Error out if too large
3842 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003843 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3844 }
3845
3846 // Casts are safe because of checks above
3847 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3848
3849 return QCBOR_SUCCESS;
3850}
3851
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003852
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003853/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003854 Compute value with signed mantissa and unsigned result. Works with
3855 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003856 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003857static inline QCBORError ExponentitateNU(int64_t nMantissa,
3858 int64_t nExponent,
3859 uint64_t *puResult,
3860 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003861{
3862 if(nMantissa < 0) {
3863 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3864 }
3865
3866 // Cast to unsigned is OK because of check for negative
3867 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3868 // Exponentiation is straight forward
3869 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3870}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003871
3872
3873/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003874 Compute value with signed mantissa and unsigned result. Works with
3875 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003876 */
3877static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3878 int64_t nExponent,
3879 uint64_t *puResult,
3880 fExponentiator pfExp)
3881{
3882 return (*pfExp)(uMantissa, nExponent, puResult);
3883}
3884
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003885#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3886
3887
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003888
3889
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003890
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003891static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003892{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003893 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003894
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003895 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003896 const uint8_t *pByte = BigNum.ptr;
3897 size_t uLen = BigNum.len;
3898 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003899 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003900 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003901 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003902 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003903 }
3904
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003905 *pResult = uResult;
3906 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003907}
3908
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003909
Laurence Lundblade887add82020-05-17 05:50:34 -07003910static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003912 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003913}
3914
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003915
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003916static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917{
3918 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003919 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3920 if(uError) {
3921 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003922 }
3923 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3924 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003925 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003926}
3927
3928
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003929static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003930{
3931 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003932 /* The negative integer furthest from zero for a C int64_t is
3933 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3934 negative number in CBOR is computed as -n - 1 where n is the
3935 encoded integer, where n is what is in the variable BigNum. When
3936 converting BigNum to a uint64_t, the maximum value is thus
3937 INT64_MAX, so that when it -n - 1 is applied to it the result will
3938 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003939
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003940 -n - 1 <= INT64_MIN.
3941 -n - 1 <= -INT64_MAX - 1
3942 n <= INT64_MAX.
3943 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003944 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003945 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003946 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003947 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003948
3949 /// Now apply -n - 1. The cast is safe because
3950 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3951 // is the largest positive integer that an int64_t can
3952 // represent. */
3953 *pnResult = -(int64_t)uResult - 1;
3954
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003955 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003956}
3957
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003958
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003959
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003960
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003961
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003962/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003963Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003964
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003965\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003966
Laurence Lundblade93d89472020-10-03 22:30:50 -07003967\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3968 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003969
3970\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3971
Laurence Lundblade93d89472020-10-03 22:30:50 -07003972\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3973 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003975static QCBORError
3976ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003977{
3978 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003979 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003980 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003981#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003983 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3984 http://www.cplusplus.com/reference/cmath/llround/
3985 */
3986 // Not interested in FE_INEXACT
3987 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003988 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3989 *pnValue = llround(pItem->val.dfnum);
3990 } else {
3991 *pnValue = lroundf(pItem->val.fnum);
3992 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003993 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3994 // llround() shouldn't result in divide by zero, but catch
3995 // it here in case it unexpectedly does. Don't try to
3996 // distinguish between the various exceptions because it seems
3997 // they vary by CPU, compiler and OS.
3998 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999 }
4000 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004001 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004002 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004003#else
4004 return QCBOR_ERR_HW_FLOAT_DISABLED;
4005#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004006 break;
4007
4008 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004009 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004010 *pnValue = pItem->val.int64;
4011 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004012 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004013 }
4014 break;
4015
4016 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004018 if(pItem->val.uint64 < INT64_MAX) {
4019 *pnValue = pItem->val.int64;
4020 } else {
4021 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4022 }
4023 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004024 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004025 }
4026 break;
4027
4028 default:
4029 return QCBOR_ERR_UNEXPECTED_TYPE;
4030 }
4031 return QCBOR_SUCCESS;
4032}
4033
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004034
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004035void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004036 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004037 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004038 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004039{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004040 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004041 return;
4042 }
4043
Laurence Lundbladee6430642020-03-14 21:15:44 -07004044 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004045 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4046 if(uError) {
4047 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004048 return;
4049 }
4050
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004051 if(pItem) {
4052 *pItem = Item;
4053 }
4054
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004055 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004056}
4057
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004058
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004059void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4060 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004061 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004062 int64_t *pnValue,
4063 QCBORItem *pItem)
4064{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004065 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004066 if(pMe->uLastError != QCBOR_SUCCESS) {
4067 return;
4068 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004070 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004071}
4072
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004073
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004074void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4075 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004076 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077 int64_t *pnValue,
4078 QCBORItem *pItem)
4079{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004080 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004081 if(pMe->uLastError != QCBOR_SUCCESS) {
4082 return;
4083 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004085 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004086}
4087
4088
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004089/*
4090 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004093
Laurence Lundblade93d89472020-10-03 22:30:50 -07004094 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4095 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004096
4097 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4098
Laurence Lundblade93d89472020-10-03 22:30:50 -07004099 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4100 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004101 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004102static QCBORError
4103Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004104{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004105 switch(pItem->uDataType) {
4106
4107 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004108 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004109 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004110 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004112 }
4113 break;
4114
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004115 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004116 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004117 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004118 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004119 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004120 }
4121 break;
4122
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4124 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004125 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004126 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004127 pItem->val.expAndMantissa.nExponent,
4128 pnValue,
4129 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004130 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004131 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004132 }
4133 break;
4134
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004135 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004136 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004137 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004138 pItem->val.expAndMantissa.nExponent,
4139 pnValue,
4140 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004141 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004142 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004143 }
4144 break;
4145
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004146 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004147 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004148 int64_t nMantissa;
4149 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4151 if(uErr) {
4152 return uErr;
4153 }
4154 return ExponentiateNN(nMantissa,
4155 pItem->val.expAndMantissa.nExponent,
4156 pnValue,
4157 Exponentitate10);
4158 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004159 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160 }
4161 break;
4162
4163 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004165 int64_t nMantissa;
4166 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4168 if(uErr) {
4169 return uErr;
4170 }
4171 return ExponentiateNN(nMantissa,
4172 pItem->val.expAndMantissa.nExponent,
4173 pnValue,
4174 Exponentitate10);
4175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
4178 break;
4179
4180 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004182 int64_t nMantissa;
4183 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004184 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4185 if(uErr) {
4186 return uErr;
4187 }
4188 return ExponentiateNN(nMantissa,
4189 pItem->val.expAndMantissa.nExponent,
4190 pnValue,
4191 Exponentitate2);
4192 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004193 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194 }
4195 break;
4196
4197 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004198 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004199 int64_t nMantissa;
4200 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4202 if(uErr) {
4203 return uErr;
4204 }
4205 return ExponentiateNN(nMantissa,
4206 pItem->val.expAndMantissa.nExponent,
4207 pnValue,
4208 Exponentitate2);
4209 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004210 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004211 }
4212 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004213#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4214
Laurence Lundbladee6430642020-03-14 21:15:44 -07004215
Laurence Lundbladec4537442020-04-14 18:53:22 -07004216 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004217 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004218}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004219
4220
Laurence Lundbladec4537442020-04-14 18:53:22 -07004221/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004222 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004223 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004224void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004225{
4226 QCBORItem Item;
4227
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004228 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004229
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004230 if(pMe->uLastError == QCBOR_SUCCESS) {
4231 // The above conversion succeeded
4232 return;
4233 }
4234
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004235 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004236 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004237 return;
4238 }
4239
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004240 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004241}
4242
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004243
4244/*
4245Public function, see header qcbor/qcbor_decode.h file
4246*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004247void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4248 int64_t nLabel,
4249 uint32_t uConvertTypes,
4250 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004251{
4252 QCBORItem Item;
4253
Laurence Lundblade93d89472020-10-03 22:30:50 -07004254 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4255 nLabel,
4256 uConvertTypes,
4257 pnValue,
4258 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004259
4260 if(pMe->uLastError == QCBOR_SUCCESS) {
4261 // The above conversion succeeded
4262 return;
4263 }
4264
4265 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4266 // The above conversion failed in a way that code below can't correct
4267 return;
4268 }
4269
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004270 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004271}
4272
4273
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004274/*
4275Public function, see header qcbor/qcbor_decode.h file
4276*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004277void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4278 const char *szLabel,
4279 uint32_t uConvertTypes,
4280 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004281{
4282 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004283 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4284 szLabel,
4285 uConvertTypes,
4286 pnValue,
4287 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004288
4289 if(pMe->uLastError == QCBOR_SUCCESS) {
4290 // The above conversion succeeded
4291 return;
4292 }
4293
4294 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4295 // The above conversion failed in a way that code below can't correct
4296 return;
4297 }
4298
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004299 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004300}
4301
4302
Laurence Lundblade93d89472020-10-03 22:30:50 -07004303static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004304{
4305 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004306 case QCBOR_TYPE_DOUBLE:
4307 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004308#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004309 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004310 // Can't use llround here because it will not convert values
4311 // greater than INT64_MAX and less than UINT64_MAX that
4312 // need to be converted so it is more complicated.
4313 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4314 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4315 if(isnan(pItem->val.dfnum)) {
4316 return QCBOR_ERR_FLOAT_EXCEPTION;
4317 } else if(pItem->val.dfnum < 0) {
4318 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4319 } else {
4320 double dRounded = round(pItem->val.dfnum);
4321 // See discussion in DecodeDateEpoch() for
4322 // explanation of - 0x7ff
4323 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4324 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4325 }
4326 *puValue = (uint64_t)dRounded;
4327 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004328 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004329 if(isnan(pItem->val.fnum)) {
4330 return QCBOR_ERR_FLOAT_EXCEPTION;
4331 } else if(pItem->val.fnum < 0) {
4332 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4333 } else {
4334 float fRounded = roundf(pItem->val.fnum);
4335 // See discussion in DecodeDateEpoch() for
4336 // explanation of - 0x7ff
4337 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4338 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4339 }
4340 *puValue = (uint64_t)fRounded;
4341 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004342 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004343 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4344 // round() and roundf() shouldn't result in exceptions here, but
4345 // catch them to be robust and thorough. Don't try to
4346 // distinguish between the various exceptions because it seems
4347 // they vary by CPU, compiler and OS.
4348 return QCBOR_ERR_FLOAT_EXCEPTION;
4349 }
4350
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004351 } else {
4352 return QCBOR_ERR_UNEXPECTED_TYPE;
4353 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004354#else
4355 return QCBOR_ERR_HW_FLOAT_DISABLED;
4356#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004357 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004358
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004359 case QCBOR_TYPE_INT64:
4360 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4361 if(pItem->val.int64 >= 0) {
4362 *puValue = (uint64_t)pItem->val.int64;
4363 } else {
4364 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4365 }
4366 } else {
4367 return QCBOR_ERR_UNEXPECTED_TYPE;
4368 }
4369 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004371 case QCBOR_TYPE_UINT64:
4372 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4373 *puValue = pItem->val.uint64;
4374 } else {
4375 return QCBOR_ERR_UNEXPECTED_TYPE;
4376 }
4377 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004378
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004379 default:
4380 return QCBOR_ERR_UNEXPECTED_TYPE;
4381 }
4382
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004383 return QCBOR_SUCCESS;
4384}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004385
4386
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004387void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004388 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004390 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004392 if(pMe->uLastError != QCBOR_SUCCESS) {
4393 return;
4394 }
4395
Laurence Lundbladec4537442020-04-14 18:53:22 -07004396 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004397
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004398 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4399 if(uError) {
4400 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004401 return;
4402 }
4403
Laurence Lundbladea826c502020-05-10 21:07:00 -07004404 if(pItem) {
4405 *pItem = Item;
4406 }
4407
Laurence Lundblade93d89472020-10-03 22:30:50 -07004408 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004409}
4410
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004411
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004412void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004414 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004415 uint64_t *puValue,
4416 QCBORItem *pItem)
4417{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004418 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004419 if(pMe->uLastError != QCBOR_SUCCESS) {
4420 return;
4421 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422
Laurence Lundblade93d89472020-10-03 22:30:50 -07004423 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424}
4425
4426
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004427void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004429 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430 uint64_t *puValue,
4431 QCBORItem *pItem)
4432{
4433 if(pMe->uLastError != QCBOR_SUCCESS) {
4434 return;
4435 }
4436
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004437 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004438 if(pMe->uLastError != QCBOR_SUCCESS) {
4439 return;
4440 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441
Laurence Lundblade93d89472020-10-03 22:30:50 -07004442 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004443}
4444
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004445
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004446
Laurence Lundblade93d89472020-10-03 22:30:50 -07004447static QCBORError
4448UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004450 switch(pItem->uDataType) {
4451
4452 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004453 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4455 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004456 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 }
4458 break;
4459
4460 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4463 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004464 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004465 }
4466 break;
4467
4468#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4469
4470 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004471 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004473 pItem->val.expAndMantissa.nExponent,
4474 puValue,
4475 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004477 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004478 }
4479 break;
4480
4481 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004482 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004483 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4484 pItem->val.expAndMantissa.nExponent,
4485 puValue,
4486 Exponentitate2);
4487 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004489 }
4490 break;
4491
4492 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004493 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004494 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004495 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004496 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497 if(uErr != QCBOR_SUCCESS) {
4498 return uErr;
4499 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004500 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 pItem->val.expAndMantissa.nExponent,
4502 puValue,
4503 Exponentitate10);
4504 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 }
4507 break;
4508
4509 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004510 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004511 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4512 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004513 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004514 }
4515 break;
4516
4517 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004518 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004519 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004520 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004521 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004522 if(uErr != QCBOR_SUCCESS) {
4523 return uErr;
4524 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004525 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526 pItem->val.expAndMantissa.nExponent,
4527 puValue,
4528 Exponentitate2);
4529 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004530 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531 }
4532 break;
4533
4534 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004535 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004536 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4537 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004538 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004539 }
4540 break;
4541#endif
4542 default:
4543 return QCBOR_ERR_UNEXPECTED_TYPE;
4544 }
4545}
4546
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004547
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004548/*
4549 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004550 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004551void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004552{
4553 QCBORItem Item;
4554
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004556
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004557 if(pMe->uLastError == QCBOR_SUCCESS) {
4558 // The above conversion succeeded
4559 return;
4560 }
4561
4562 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4563 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004564 return;
4565 }
4566
Laurence Lundblade93d89472020-10-03 22:30:50 -07004567 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004568}
4569
Laurence Lundbladec4537442020-04-14 18:53:22 -07004570
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004572 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004573*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004574void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004575 int64_t nLabel,
4576 uint32_t uConvertTypes,
4577 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004578{
4579 QCBORItem Item;
4580
Laurence Lundblade93d89472020-10-03 22:30:50 -07004581 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4582 nLabel,
4583 uConvertTypes,
4584 puValue,
4585 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004586
4587 if(pMe->uLastError == QCBOR_SUCCESS) {
4588 // The above conversion succeeded
4589 return;
4590 }
4591
4592 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4593 // The above conversion failed in a way that code below can't correct
4594 return;
4595 }
4596
Laurence Lundblade93d89472020-10-03 22:30:50 -07004597 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598}
4599
4600
4601/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004602 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004604void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004605 const char *szLabel,
4606 uint32_t uConvertTypes,
4607 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608{
4609 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004610 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4611 szLabel,
4612 uConvertTypes,
4613 puValue,
4614 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615
4616 if(pMe->uLastError == QCBOR_SUCCESS) {
4617 // The above conversion succeeded
4618 return;
4619 }
4620
4621 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4622 // The above conversion failed in a way that code below can't correct
4623 return;
4624 }
4625
Laurence Lundblade93d89472020-10-03 22:30:50 -07004626 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004627}
4628
4629
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004630
4631
Laurence Lundblade9b334962020-08-27 10:55:53 -07004632static QCBORError ConvertDouble(const QCBORItem *pItem,
4633 uint32_t uConvertTypes,
4634 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004635{
4636 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004637 case QCBOR_TYPE_FLOAT:
4638#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4639 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4640 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004641 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004642 *pdValue = (double)pItem->val.fnum;
4643 } else {
4644 return QCBOR_ERR_UNEXPECTED_TYPE;
4645 }
4646 }
4647#else
4648 return QCBOR_ERR_HW_FLOAT_DISABLED;
4649#endif
4650 break;
4651
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004652 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004653 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4654 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004655 *pdValue = pItem->val.dfnum;
4656 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004657 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004658 }
4659 }
4660 break;
4661
4662 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004663#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004664 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004665 // A simple cast seems to do the job with no worry of exceptions.
4666 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004667 *pdValue = (double)pItem->val.int64;
4668
4669 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004672#else
4673 return QCBOR_ERR_HW_FLOAT_DISABLED;
4674#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 break;
4676
4677 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004678#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004679 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004680 // A simple cast seems to do the job with no worry of exceptions.
4681 // There will be precision loss for some values.
4682 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004683 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004684 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 }
4686 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004687#else
4688 return QCBOR_ERR_HW_FLOAT_DISABLED;
4689#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690
4691 default:
4692 return QCBOR_ERR_UNEXPECTED_TYPE;
4693 }
4694
4695 return QCBOR_SUCCESS;
4696}
4697
4698
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004699void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004702 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004703{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004704 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004705 return;
4706 }
4707
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004708 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004709
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004710 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004711 if(uError) {
4712 pMe->uLastError = (uint8_t)uError;
4713 return;
4714 }
4715
4716 if(pItem) {
4717 *pItem = Item;
4718 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004719
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004721}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004722
Laurence Lundbladec4537442020-04-14 18:53:22 -07004723
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004724void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4725 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 double *pdValue,
4728 QCBORItem *pItem)
4729{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004730 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004731 if(pMe->uLastError != QCBOR_SUCCESS) {
4732 return;
4733 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004736}
4737
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004738
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004739void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4740 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004742 double *pdValue,
4743 QCBORItem *pItem)
4744{
4745 if(pMe->uLastError != QCBOR_SUCCESS) {
4746 return;
4747 }
4748
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004749 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004750 if(pMe->uLastError != QCBOR_SUCCESS) {
4751 return;
4752 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004754 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004755}
4756
4757
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004758#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004759static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4760{
4761 double dResult;
4762
4763 dResult = 0.0;
4764 const uint8_t *pByte = BigNum.ptr;
4765 size_t uLen = BigNum.len;
4766 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004767 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004768 while(uLen--) {
4769 dResult = (dResult * 256.0) + (double)*pByte++;
4770 }
4771
4772 return dResult;
4773}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004774#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4775
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004776
Laurence Lundblade93d89472020-10-03 22:30:50 -07004777static QCBORError
4778DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004779{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004780#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004781 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004782 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4783
4784 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004786
4787#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004788 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004790 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004791 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4792 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
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:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004800 // Underflow gives 0, overflow gives infinity
4801 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4802 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004803 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 }
4806 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004807#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808
4809 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004810 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004811 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4812 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004813 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814 }
4815 break;
4816
4817 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004818 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004819 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004821 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822 }
4823 break;
4824
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004825#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004827 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004828 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4829 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4830 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 }
4833 break;
4834
4835 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004836 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4838 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4839 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004840 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841 }
4842 break;
4843
4844 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4847 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4848 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004849 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 }
4851 break;
4852
4853 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004854 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004855 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4857 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 }
4860 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004861#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4862
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 default:
4864 return QCBOR_ERR_UNEXPECTED_TYPE;
4865 }
4866
4867 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004868
4869#else
4870 (void)pItem;
4871 (void)uConvertTypes;
4872 (void)pdValue;
4873 return QCBOR_ERR_HW_FLOAT_DISABLED;
4874#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4875
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876}
4877
4878
4879/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004880 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004882void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4883 uint32_t uConvertTypes,
4884 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885{
4886
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004887 QCBORItem Item;
4888
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004889 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004890
4891 if(pMe->uLastError == QCBOR_SUCCESS) {
4892 // The above conversion succeeded
4893 return;
4894 }
4895
4896 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4897 // The above conversion failed in a way that code below can't correct
4898 return;
4899 }
4900
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004902}
4903
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004904
4905/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004906 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004907*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004908void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4909 int64_t nLabel,
4910 uint32_t uConvertTypes,
4911 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912{
4913 QCBORItem Item;
4914
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004915 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004916
4917 if(pMe->uLastError == QCBOR_SUCCESS) {
4918 // The above conversion succeeded
4919 return;
4920 }
4921
4922 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4923 // The above conversion failed in a way that code below can't correct
4924 return;
4925 }
4926
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004927 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004928}
4929
4930
4931/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004932 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004933*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004934void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4935 const char *szLabel,
4936 uint32_t uConvertTypes,
4937 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004938{
4939 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004940 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004941
4942 if(pMe->uLastError == QCBOR_SUCCESS) {
4943 // The above conversion succeeded
4944 return;
4945 }
4946
4947 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4948 // The above conversion failed in a way that code below can't correct
4949 return;
4950 }
4951
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004952 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004953}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004954
4955
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004956
4957
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004958#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004959static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4960{
4961 while((uInt & 0xff00000000000000UL) == 0) {
4962 uInt = uInt << 8;
4963 };
4964
4965 UsefulOutBuf UOB;
4966
4967 UsefulOutBuf_Init(&UOB, Buffer);
4968
4969 while(uInt) {
4970 const uint64_t xx = uInt & 0xff00000000000000UL;
4971 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4972 uInt = uInt << 8;
4973 (void)xx;
4974 }
4975
4976 return UsefulOutBuf_OutUBuf(&UOB);
4977}
4978
4979
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004980static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4981 TagSpecification TagSpec,
4982 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004983{
4984 QCBORError uErr;
4985 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004986 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004987 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004988 if(uErr != QCBOR_SUCCESS) {
4989 goto Done;
4990 }
4991
4992 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4993 break; // Successful exit. Moving on to finish decoding.
4994 }
4995
4996 // The item is an array, which means an undecoded
4997 // mantissa and exponent, so decode it. It will then
4998 // have a different type and exit the loop if.
4999 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5000 if(uErr != QCBOR_SUCCESS) {
5001 goto Done;
5002 }
5003
5004 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005005 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005006 }
5007Done:
5008 return uErr;
5009}
5010
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005011
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005012static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005013 TagSpecification TagSpec,
5014 QCBORItem *pItem,
5015 int64_t *pnMantissa,
5016 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005017{
5018 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005019
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005020 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005021 if(uErr != QCBOR_SUCCESS) {
5022 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005023 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005024
Laurence Lundblade9b334962020-08-27 10:55:53 -07005025 switch (pItem->uDataType) {
5026
5027 case QCBOR_TYPE_DECIMAL_FRACTION:
5028 case QCBOR_TYPE_BIGFLOAT:
5029 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5030 *pnExponent = pItem->val.expAndMantissa.nExponent;
5031 break;
5032
5033 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5034 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5035 *pnExponent = pItem->val.expAndMantissa.nExponent;
5036 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5037 break;
5038
5039 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5040 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5041 *pnExponent = pItem->val.expAndMantissa.nExponent;
5042 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5043 break;
5044
5045 default:
5046 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5047 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005048
5049 Done:
5050 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005051}
5052
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005053
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005054static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005055 TagSpecification TagSpec,
5056 QCBORItem *pItem,
5057 UsefulBuf BufferForMantissa,
5058 UsefulBufC *pMantissa,
5059 bool *pbIsNegative,
5060 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005062 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005064 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005065 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005066 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005067 }
5068
5069 uint64_t uMantissa;
5070
5071 switch (pItem->uDataType) {
5072
5073 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005074 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5076 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5077 *pbIsNegative = false;
5078 } else {
5079 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5080 *pbIsNegative = true;
5081 }
5082 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5083 *pnExponent = pItem->val.expAndMantissa.nExponent;
5084 break;
5085
5086 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005087 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005088 *pnExponent = pItem->val.expAndMantissa.nExponent;
5089 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5090 *pbIsNegative = false;
5091 break;
5092
5093 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005094 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005095 *pnExponent = pItem->val.expAndMantissa.nExponent;
5096 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5097 *pbIsNegative = true;
5098 break;
5099
5100 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005101 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005102 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005103
5104Done:
5105 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005106}
5107
5108
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005109/*
5110 Public function, see header qcbor/qcbor_decode.h file
5111*/
5112void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5113 uint8_t uTagRequirement,
5114 int64_t *pnMantissa,
5115 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005116{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005117 if(pMe->uLastError != QCBOR_SUCCESS) {
5118 return;
5119 }
5120
5121 QCBORItem Item;
5122 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5123 if(uError) {
5124 pMe->uLastError = (uint8_t)uError;
5125 return;
5126 }
5127
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005128 const TagSpecification TagSpec =
5129 {
5130 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005131 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5132 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5133 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005134 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005135
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005136 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005137}
5138
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005139
5140/*
5141 Public function, see header qcbor/qcbor_decode.h file
5142*/
5143void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005145 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005146 int64_t *pnMantissa,
5147 int64_t *pnExponent)
5148{
5149 if(pMe->uLastError != QCBOR_SUCCESS) {
5150 return;
5151 }
5152
5153 QCBORItem Item;
5154 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5155
5156 const TagSpecification TagSpec =
5157 {
5158 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005159 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5160 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5161 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005162 };
5163
5164 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5165}
5166
5167
5168/*
5169 Public function, see header qcbor/qcbor_decode.h file
5170*/
5171void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005172 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005173 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005174 int64_t *pnMantissa,
5175 int64_t *pnExponent)
5176{
5177 if(pMe->uLastError != QCBOR_SUCCESS) {
5178 return;
5179 }
5180
5181 QCBORItem Item;
5182 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5183
5184 const TagSpecification TagSpec =
5185 {
5186 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005187 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5188 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5189 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005191
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005192 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5193}
5194
5195
5196/*
5197 Public function, see header qcbor/qcbor_decode.h file
5198*/
5199void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5200 uint8_t uTagRequirement,
5201 UsefulBuf MantissaBuffer,
5202 UsefulBufC *pMantissa,
5203 bool *pbMantissaIsNegative,
5204 int64_t *pnExponent)
5205{
5206 if(pMe->uLastError != QCBOR_SUCCESS) {
5207 return;
5208 }
5209
5210 QCBORItem Item;
5211 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5212 if(uError) {
5213 pMe->uLastError = (uint8_t)uError;
5214 return;
5215 }
5216
5217 const TagSpecification TagSpec =
5218 {
5219 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005220 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5221 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5222 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005223 };
5224
Laurence Lundblade93d89472020-10-03 22:30:50 -07005225 ProcessMantissaAndExponentBig(pMe,
5226 TagSpec,
5227 &Item,
5228 MantissaBuffer,
5229 pMantissa,
5230 pbMantissaIsNegative,
5231 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005232}
5233
5234
5235/*
5236 Public function, see header qcbor/qcbor_decode.h file
5237*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005238void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005239 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005240 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005241 UsefulBuf BufferForMantissa,
5242 UsefulBufC *pMantissa,
5243 bool *pbIsNegative,
5244 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005245{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005246 if(pMe->uLastError != QCBOR_SUCCESS) {
5247 return;
5248 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005249
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005250 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005251 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005252 if(pMe->uLastError != QCBOR_SUCCESS) {
5253 return;
5254 }
5255
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005256 const TagSpecification TagSpec =
5257 {
5258 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005259 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5260 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5261 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005262 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005263
Laurence Lundblade93d89472020-10-03 22:30:50 -07005264 ProcessMantissaAndExponentBig(pMe,
5265 TagSpec,
5266 &Item,
5267 BufferForMantissa,
5268 pMantissa,
5269 pbIsNegative,
5270 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005271}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005272
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005273
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005274/*
5275 Public function, see header qcbor/qcbor_decode.h file
5276*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005277void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005278 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005279 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005280 UsefulBuf BufferForMantissa,
5281 UsefulBufC *pMantissa,
5282 bool *pbIsNegative,
5283 int64_t *pnExponent)
5284{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005285 if(pMe->uLastError != QCBOR_SUCCESS) {
5286 return;
5287 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005288
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005289 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005290 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5291 if(pMe->uLastError != QCBOR_SUCCESS) {
5292 return;
5293 }
5294
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 const TagSpecification TagSpec =
5296 {
5297 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005298 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5299 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5300 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005301 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005302
5303 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5304}
5305
5306
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307/*
5308 Public function, see header qcbor/qcbor_decode.h file
5309*/
5310void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5311 uint8_t uTagRequirement,
5312 int64_t *pnMantissa,
5313 int64_t *pnExponent)
5314{
5315 if(pMe->uLastError != QCBOR_SUCCESS) {
5316 return;
5317 }
5318
5319 QCBORItem Item;
5320 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5321 if(uError) {
5322 pMe->uLastError = (uint8_t)uError;
5323 return;
5324 }
5325 const TagSpecification TagSpec =
5326 {
5327 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005328 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5329 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5330 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005331 };
5332
5333 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5334}
5335
5336
5337/*
5338 Public function, see header qcbor/qcbor_decode.h file
5339*/
5340void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005342 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005343 int64_t *pnMantissa,
5344 int64_t *pnExponent)
5345{
5346 if(pMe->uLastError != QCBOR_SUCCESS) {
5347 return;
5348 }
5349
5350 QCBORItem Item;
5351 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5352 if(pMe->uLastError != QCBOR_SUCCESS) {
5353 return;
5354 }
5355
5356 const TagSpecification TagSpec =
5357 {
5358 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005359 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5360 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5361 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005362 };
5363
5364 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5365}
5366
5367
5368/*
5369 Public function, see header qcbor/qcbor_decode.h file
5370*/
5371void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005373 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005374 int64_t *pnMantissa,
5375 int64_t *pnExponent)
5376{
5377 if(pMe->uLastError != QCBOR_SUCCESS) {
5378 return;
5379 }
5380
5381 QCBORItem Item;
5382 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5383 if(pMe->uLastError != QCBOR_SUCCESS) {
5384 return;
5385 }
5386
5387 const TagSpecification TagSpec =
5388 {
5389 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005390 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5391 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5392 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005393 };
5394
5395 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5396}
5397
5398
5399/*
5400 Public function, see header qcbor/qcbor_decode.h file
5401*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005402void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5403 uint8_t uTagRequirement,
5404 UsefulBuf MantissaBuffer,
5405 UsefulBufC *pMantissa,
5406 bool *pbMantissaIsNegative,
5407 int64_t *pnExponent)
5408{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005409 if(pMe->uLastError != QCBOR_SUCCESS) {
5410 return;
5411 }
5412
5413 QCBORItem Item;
5414 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5415 if(uError) {
5416 pMe->uLastError = (uint8_t)uError;
5417 return;
5418 }
5419
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005420 const TagSpecification TagSpec =
5421 {
5422 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005423 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5424 QCBOR_TYPE_BIGFLOAT_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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005427
5428 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005429}
5430
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005431
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005432/*
5433 Public function, see header qcbor/qcbor_decode.h file
5434*/
5435void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005437 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 UsefulBuf BufferForMantissa,
5439 UsefulBufC *pMantissa,
5440 bool *pbIsNegative,
5441 int64_t *pnExponent)
5442{
5443 if(pMe->uLastError != QCBOR_SUCCESS) {
5444 return;
5445 }
5446
5447 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005448 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5449 if(pMe->uLastError != QCBOR_SUCCESS) {
5450 return;
5451 }
5452
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453 const TagSpecification TagSpec =
5454 {
5455 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005456 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5457 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5458 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005459 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005460
Laurence Lundblade93d89472020-10-03 22:30:50 -07005461 ProcessMantissaAndExponentBig(pMe,
5462 TagSpec,
5463 &Item,
5464 BufferForMantissa,
5465 pMantissa,
5466 pbIsNegative,
5467 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005468}
5469
5470
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005471/*
5472 Public function, see header qcbor/qcbor_decode.h file
5473*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005474void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005475 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005476 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477 UsefulBuf BufferForMantissa,
5478 UsefulBufC *pMantissa,
5479 bool *pbIsNegative,
5480 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005481{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482 if(pMe->uLastError != QCBOR_SUCCESS) {
5483 return;
5484 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005485
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005486 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005487 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5488 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005489 return;
5490 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005491
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005492 const TagSpecification TagSpec =
5493 {
5494 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005495 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5496 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5497 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005498 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005499
Laurence Lundblade93d89472020-10-03 22:30:50 -07005500 ProcessMantissaAndExponentBig(pMe,
5501 TagSpec,
5502 &Item,
5503 BufferForMantissa,
5504 pMantissa,
5505 pbIsNegative,
5506 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005507}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005508
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005509#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */