blob: f8e0aa8c07e832017b339621eba6c60f214d8715 [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 Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade323f8a92020-09-06 19:43:09 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf(),
40 // pow(), exp2()
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070041#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundbladec7114722020-08-13 05:11:40 -070042#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053045/*
46 This casts away the const-ness of a pointer, usually so it can be
47 freed or realloced.
48 */
49#define UNCONST_POINTER(ptr) ((void *)(ptr))
50
Laurence Lundbladea9489f82020-09-12 13:50:56 -070051#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundblade02625d42020-06-25 14:41:41 -070054inline static bool
55// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
56QCBORItem_IsMapOrArray(const QCBORItem *pMe)
57{
58 const uint8_t uDataType = pMe->uDataType;
59 return uDataType == QCBOR_TYPE_MAP ||
60 uDataType == QCBOR_TYPE_ARRAY ||
61 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
62}
63
64inline static bool
65QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
66{
67 if(!QCBORItem_IsMapOrArray(pMe)){
68 return false;
69 }
70
71 if(pMe->val.uCount != 0) {
72 return false;
73 }
74 return true;
75}
76
77inline static bool
78QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
79{
80 if(!QCBORItem_IsMapOrArray(pMe)){
81 return false;
82 }
83
84 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
85 return false;
86 }
87 return true;
88}
89
90
Laurence Lundbladeee851742020-01-08 08:37:05 -080091/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070092 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080093 ===========================================================================*/
94
Laurence Lundblade9c905e82020-04-25 11:31:38 -070095/*
Laurence Lundblade93d89472020-10-03 22:30:50 -070096 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h,
97 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098 */
99
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700100
101inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700102DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700103{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700104 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105 /*
106 Limit in DecodeNesting_Descend against more than
107 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
108 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700109 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110}
111
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700112
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700113inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700115{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700116 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 /*
118 Limit in DecodeNesting_Descend against more than
119 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
120 */
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 Lundblade9c905e82020-04-25 11:31:38 -0700143inline static 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 Lundblade3f9ef042020-04-14 13:15:51 -0700154inline static 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 Lundbladea8edadb2020-06-27 22:35:37 -0700158 // 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 Lundbladea8edadb2020-06-27 22:35:37 -0700162 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700165 // 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 Lundblade642282a2020-06-23 12:00:33 -0700170inline static 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 Lundbladea8edadb2020-06-27 22:35:37 -0700174 // 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 Lundblade6c8a4442020-06-22 22:16:11 -0700181inline static 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 Lundblade085d7952020-07-24 10:26:30 -0700193inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700196 /*
197 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.
200 */
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 Lundbladea8edadb2020-06-27 22:35:37 -0700209inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700215inline static 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 Lundblade6ab01fb2020-10-01 13:04:49 -0700219 // 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 Lundblade6ab01fb2020-10-01 13:04:49 -0700223 // 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)) {
227 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700230 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700235 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252inline static bool
253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700263inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700286inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
294inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700306 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700318inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700326
327 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
328 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700329 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700330 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700331 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700332 }
333
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700334 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700335
336 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700337
338 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700339}
340
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700341
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700342inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 uint8_t uQCBORType,
345 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348
349 if(uCount == 0) {
350 // Nothing to do for empty definite lenth arrays. They are just are
351 // effectively the same as an item that is not a map or array
352 goto Done;
353 // Empty indefinite length maps and arrays are handled elsewhere
354 }
355
356 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
358 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700359 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360 goto Done;
361 }
362
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700363 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
366 }
367
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700368 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700369 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
370 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700371
372 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373
374Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 return uError;;
376}
377
378
379static inline void
380DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
381{
382 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
383}
384
385
386static inline void
387DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
388{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700390 pNesting->pCurrentBounded--;
391 if(DecodeNesting_IsCurrentBounded(pNesting)) {
392 break;
393 }
394 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395}
396
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700397static inline void
398DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded;
401}
402
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700404inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700406 uint32_t uEndOffset,
407 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700411 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 goto Done;
414 }
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700417 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
418 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421 pNesting->pCurrentBounded = pNesting->pCurrent;
422
423Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 return uError;;
425}
426
Laurence Lundbladed0304932020-06-27 10:59:38 -0700427
428static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430{
431 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432}
433
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
Laurence Lundbladeee851742020-01-08 08:37:05 -0800435inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700436DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700437{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700439 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
440 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700441}
442
443
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700444inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700445DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700446{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700447 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700448 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700450}
451
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700452
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700454DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700455{
456 *pNesting = *pSave;
457}
458
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462{
463 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
464}
465
466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700468DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700469{
470 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
471}
472
473
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700474
Laurence Lundbladeee851742020-01-08 08:37:05 -0800475/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800476 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
477
478 The following four functions are pretty wrappers for invocation of
479 the string allocator supplied by the caller.
480
Laurence Lundbladeee851742020-01-08 08:37:05 -0800481 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800482
Laurence Lundbladeee851742020-01-08 08:37:05 -0800483static inline void
484StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485{
486 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
487}
488
Laurence Lundbladeee851742020-01-08 08:37:05 -0800489// StringAllocator_Reallocate called with pMem NULL is
490// equal to StringAllocator_Allocate()
491static inline UsefulBuf
492StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
493 void *pMem,
494 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800495{
496 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
497}
498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499static inline UsefulBuf
500StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800501{
502 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
503}
504
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505static inline void
506StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800507{
508 if(pMe->pfAllocator) {
509 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
510 }
511}
512
513
514
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515/*===========================================================================
516 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800518 See qcbor/qcbor_decode.h for definition of the object
519 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800520 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700521/*
522 Public function, see header file
523 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800524void QCBORDecode_Init(QCBORDecodeContext *me,
525 UsefulBufC EncodedCBOR,
526 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527{
528 memset(me, 0, sizeof(QCBORDecodeContext));
529 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800530 // Don't bother with error check on decode mode. If a bad value is
531 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700532 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700533 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700534 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700535 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700536 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700537}
538
539
540/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700541 Public function, see header file
542 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
544 QCBORStringAllocate pfAllocateFunction,
545 void *pAllocateContext,
546 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700547{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800548 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
549 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
550 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700551}
552
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800553
554/*
555 Public function, see header file
556 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700557void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800558 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700559{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700560 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700561 (void)pMe;
562 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700563}
564
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700565
566/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567 This decodes the fundamental part of a CBOR data item, the type and
568 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800569
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700570 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800571
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572 This does the network->host byte order conversion. The conversion
573 here also results in the conversion for floats in addition to that
574 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800575
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700576 This returns:
577 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800578
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800579 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800580 tags and floats and length for strings and arrays
581
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800582 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800583 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800584
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585 The int type is preferred to uint8_t for some variables as this
586 avoids integer promotions, can reduce code size and makes
587 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700588
589 @retval QCBOR_ERR_UNSUPPORTED
590
591 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800593inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
594 int *pnMajorType,
595 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800596 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700598 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800599
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800601 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800602
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800604 const int nTmpMajorType = nInitialByte >> 5;
605 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800607 // Where the number or argument accumulates
608 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800610 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700611 // Need to get 1,2,4 or 8 additional argument bytes. Map
612 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800613 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800614
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800615 // Loop getting all the bytes in the argument
616 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800617 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618 // This shift and add gives the endian conversion
619 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
620 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800622 // The reserved and thus-far unused additional info values
623 nReturn = QCBOR_ERR_UNSUPPORTED;
624 goto Done;
625 } else {
626 // Less than 24, additional info is argument or 31, an indefinite length
627 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 if(UsefulInputBuf_GetError(pUInBuf)) {
632 nReturn = QCBOR_ERR_HIT_END;
633 goto Done;
634 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800635
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700636 // All successful if we got here.
637 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800639 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800641
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642Done:
643 return nReturn;
644}
645
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800648 CBOR doesn't explicitly specify two's compliment for integers but all
649 CPUs use it these days and the test vectors in the RFC are so. All
650 integers in the CBOR structure are positive and the major type
651 indicates positive or negative. CBOR can express positive integers
652 up to 2^x - 1 where x is the number of bits and negative integers
653 down to 2^x. Note that negative numbers can be one more away from
654 zero than positive. Stdint, as far as I can tell, uses two's
655 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800656
Laurence Lundblade9b334962020-08-27 10:55:53 -0700657 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 used carefully here, and in particular why it isn't used in the interface.
659 Also see
660 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
661
662 Int is used for values that need less than 16-bits and would be subject
663 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700664
665 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800667inline static QCBORError
668DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700670 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
673 if (uNumber <= INT64_MAX) {
674 pDecodedItem->val.int64 = (int64_t)uNumber;
675 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677 } else {
678 pDecodedItem->val.uint64 = uNumber;
679 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681 }
682 } else {
683 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684 // CBOR's representation of negative numbers lines up with the
685 // two-compliment representation. A negative integer has one
686 // more in range than a positive integer. INT64_MIN is
687 // equal to (-INT64_MAX) - 1.
688 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 } else {
692 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000693 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 nReturn = QCBOR_ERR_INT_OVERFLOW;
695 }
696 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698 return nReturn;
699}
700
701// Make sure #define value line up as DecodeSimple counts on this.
702#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
703#error QCBOR_TYPE_FALSE macro value wrong
704#endif
705
706#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
707#error QCBOR_TYPE_TRUE macro value wrong
708#endif
709
710#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
711#error QCBOR_TYPE_NULL macro value wrong
712#endif
713
714#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
715#error QCBOR_TYPE_UNDEF macro value wrong
716#endif
717
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700718#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
719#error QCBOR_TYPE_BREAK macro value wrong
720#endif
721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
723#error QCBOR_TYPE_DOUBLE macro value wrong
724#endif
725
726#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
727#error QCBOR_TYPE_FLOAT macro value wrong
728#endif
729
730/*
731 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700732
733 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
734
735 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800737inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700740 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700742 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800743 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700744 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
745 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800747
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800749 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
750 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700752 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700753#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700754 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700755 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700756 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700757 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
758 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700759#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700760 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700761#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700762 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700763 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700764 // Single precision is normally returned as a double
765 // since double is widely supported, there is no loss of
766 // precision, it makes it easy for the caller in
767 // most cases and it can be converted back to single
768 // with no loss of precision
769 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700770 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700771 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700772 {
773 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
774#ifndef QCBOR_DISABLE_FLOAT_HW_USE
775 // In the normal case, use HW to convert float to double.
776 pDecodedItem->val.dfnum = (double)f;
777 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700778#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700779 // Use of float HW is disabled, return as a float.
780 pDecodedItem->val.fnum = f;
781 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
782
783 // IEEE754_FloatToDouble() could be used here to return
784 // as a double, but it adds object code and most likely
785 // anyone disabling FLOAT HW use doesn't care about
786 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700787#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700788 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700789 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700790
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700791 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700792 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700793 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700794 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796 case CBOR_SIMPLEV_FALSE: // 20
797 case CBOR_SIMPLEV_TRUE: // 21
798 case CBOR_SIMPLEV_NULL: // 22
799 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700800 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700801 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 case CBOR_SIMPLEV_ONEBYTE: // 24
804 if(uNumber <= CBOR_SIMPLE_BREAK) {
805 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700806 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 goto Done;
808 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800809 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 default: // 0-19
813 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800814 /*
815 DecodeTypeAndNumber will make uNumber equal to
816 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
817 safe because the 2, 4 and 8 byte lengths of uNumber are in
818 the double/float cases above
819 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 pDecodedItem->val.uSimple = (uint8_t)uNumber;
821 break;
822 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800823
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700824Done:
825 return nReturn;
826}
827
828
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700829/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530830 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700831
832 @retval QCBOR_ERR_HIT_END
833
834 @retval QCBOR_ERR_STRING_ALLOCATE
835
836 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800838inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
839 int nMajorType,
840 uint64_t uStrLen,
841 UsefulInputBuf *pUInBuf,
842 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700844 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800845
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
847 // This check makes the casts to size_t below safe.
848
849 // 4 bytes less than the largest sizeof() so this can be tested by
850 // putting a SIZE_MAX length in the CBOR test input (no one will
851 // care the limit on strings is 4 bytes shorter).
852 if(uStrLen > SIZE_MAX-4) {
853 nReturn = QCBOR_ERR_STRING_TOO_LONG;
854 goto Done;
855 }
856
857 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530858 if(UsefulBuf_IsNULLC(Bytes)) {
859 // Failed to get the bytes for this string item
860 nReturn = QCBOR_ERR_HIT_END;
861 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530863
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800864 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530865 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800866 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700868 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530869 goto Done;
870 }
871 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800872 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530873 } else {
874 // Normal case with no string allocator
875 pDecodedItem->val.string = Bytes;
876 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800877 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800878 // Cast because ternary operator causes promotion to integer
879 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
880 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700883 return nReturn;
884}
885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800887
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700888
889
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890
891
Laurence Lundbladeee851742020-01-08 08:37:05 -0800892// Make sure the constants align as this is assumed by
893// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
895#error QCBOR_TYPE_ARRAY value not lined up with major type
896#endif
897#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
898#error QCBOR_TYPE_MAP value not lined up with major type
899#endif
900
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700901/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800902 This gets a single data item and decodes it including preceding
903 optional tagging. This does not deal with arrays and maps and nesting
904 except to decode the data item introducing them. Arrays and maps are
905 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladeee851742020-01-08 08:37:05 -0800907 Errors detected here include: an array that is too long to decode,
908 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700909
910 @retval QCBOR_ERR_UNSUPPORTED
911
912 @retval QCBOR_ERR_HIT_END
913
914 @retval QCBOR_ERR_INT_OVERFLOW
915
916 @retval QCBOR_ERR_STRING_ALLOCATE
917
918 @retval QCBOR_ERR_STRING_TOO_LONG
919
920 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
921
922 @retval QCBOR_ERR_BAD_TYPE_7
923
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800925static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
926 QCBORItem *pDecodedItem,
927 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700929 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800930
Laurence Lundbladeee851742020-01-08 08:37:05 -0800931 /*
932 Get the major type and the number. Number could be length of more
933 bytes or the value depending on the major type nAdditionalInfo is
934 an encoding of the length of the uNumber and is needed to decode
935 floats and doubles
936 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800939 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700941 memset(pDecodedItem, 0, sizeof(QCBORItem));
942
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800943 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladeee851742020-01-08 08:37:05 -0800945 // Error out here if we got into trouble on the type and number. The
946 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700947 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700949 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 // At this point the major type and the value are valid. We've got
952 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800953 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
955 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800956 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700957 nReturn = QCBOR_ERR_BAD_INT;
958 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700960 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800962
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
964 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
966 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
967 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
968 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530969 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800971 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700972 }
973 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
976 case CBOR_MAJOR_TYPE_MAP: // Major type 5
977 // Record the number of items in the array or map
978 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700979 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700980 goto Done;
981 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800982 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700983 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800985 // type conversion OK because of check above
986 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800988 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
990 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800994 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700995 nReturn = QCBOR_ERR_BAD_INT;
996 } else {
997 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -0700998 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700999 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundbladeee851742020-01-08 08:37:05 -08001002 case CBOR_MAJOR_TYPE_SIMPLE:
1003 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001004 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundbladeee851742020-01-08 08:37:05 -08001007 default:
1008 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 nReturn = QCBOR_ERR_UNSUPPORTED;
1010 break;
1011 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001013Done:
1014 return nReturn;
1015}
1016
1017
1018
1019/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001020 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001021 individual chunk items together into one QCBORItem using the string
1022 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001023
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301024 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001025
1026 @retval QCBOR_ERR_UNSUPPORTED
1027
1028 @retval QCBOR_ERR_HIT_END
1029
1030 @retval QCBOR_ERR_INT_OVERFLOW
1031
1032 @retval QCBOR_ERR_STRING_ALLOCATE
1033
1034 @retval QCBOR_ERR_STRING_TOO_LONG
1035
1036 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1037
1038 @retval QCBOR_ERR_BAD_TYPE_7
1039
1040 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1041
1042 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001043 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001044static inline QCBORError
1045GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001047 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001048
1049 // Get pointer to string allocator. First use is to pass it to
1050 // GetNext_Item() when option is set to allocate for *every* string.
1051 // Second use here is to allocate space to coallese indefinite
1052 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001053 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1054 &(me->StringAllocator) :
1055 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001057 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001058 nReturn = GetNext_Item(&(me->InBuf),
1059 pDecodedItem,
1060 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 if(nReturn) {
1062 goto Done;
1063 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301066 // code in this function from here down can be eliminated. Run tests, except
1067 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001069 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001070 const uint8_t uStringType = pDecodedItem->uDataType;
1071 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 goto Done; // no need to do any work here on non-string types
1073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001075 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301076 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301080 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001081 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001082 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1083 goto Done;
1084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundblade4b270642020-08-14 12:53:07 -07001086 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001087 UsefulBufC FullString = NULLUsefulBufC;
1088
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001090 // Get item for next chunk
1091 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001092 // NULL string allocator passed here. Do not need to allocate
1093 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001094 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001095 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001096 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001097 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001098
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301099 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001100 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001101 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301103 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 break;
1105 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001106
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001107 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301108 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001109 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001110 if(StringChunkItem.uDataType != uStringType ||
1111 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001112 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 break;
1114 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001115
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301116 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001117 // The first time throurgh FullString.ptr is NULL and this is
1118 // equivalent to StringAllocator_Allocate()
1119 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1120 UNCONST_POINTER(FullString.ptr),
1121 FullString.len + StringChunkItem.val.string.len);
1122
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001123 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301124 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001125 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 break;
1127 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001129 // Copy new string chunk at the end of string so far.
1130 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001131 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001132
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001133 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1134 // Getting the item failed, clean up the allocated memory
1135 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001137
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001138Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001139 return nReturn;
1140}
1141
Laurence Lundblade9b334962020-08-27 10:55:53 -07001142static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001143 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001144 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001145 } else if(uTagVal == CBOR_TAG_INVALID16) {
1146 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001147 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001148 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001149 return me->auMappedTags[x];
1150 }
1151}
1152
Laurence Lundblade9b334962020-08-27 10:55:53 -07001153
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001154/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001155 Gets all optional tag data items preceding a data item that is not an
1156 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001157
1158 @retval QCBOR_ERR_UNSUPPORTED
1159
1160 @retval QCBOR_ERR_HIT_END
1161
1162 @retval QCBOR_ERR_INT_OVERFLOW
1163
1164 @retval QCBOR_ERR_STRING_ALLOCATE
1165
1166 @retval QCBOR_ERR_STRING_TOO_LONG
1167
1168 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1169
1170 @retval QCBOR_ERR_BAD_TYPE_7
1171
1172 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1173
1174 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1175
1176 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001178static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001180{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001181 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1182 CBOR_TAG_INVALID16,
1183 CBOR_TAG_INVALID16,
1184 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001185
Laurence Lundblade9b334962020-08-27 10:55:53 -07001186 QCBORError uReturn = QCBOR_SUCCESS;
1187
Laurence Lundblade59289e52019-12-30 13:44:37 -08001188 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001189 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001190 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1191 if(uErr != QCBOR_SUCCESS) {
1192 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001193 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001195
Laurence Lundblade9b334962020-08-27 10:55:53 -07001196 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001197 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001198 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001199 break;
1200 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundblade9b334962020-08-27 10:55:53 -07001202 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1203 // No room in the tag list
1204 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1205 // Continue on to get all tags on this item even though
1206 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001207 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001209 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001210 // Slide tags over one in the array to make room at index 0
1211 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1212 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001214
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001215 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001216 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001218 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001220 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001221 break;
1222 }
1223 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1224 break;
1225 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001226 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001227 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1228 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001229 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1230 // Continue on to get all tags on this item even though
1231 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001232 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001233 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001234 }
1235
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001236 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001237 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001238 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239
1240 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001241 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001242 }
1243 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247}
1248
1249
1250/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001251 This layer takes care of map entries. It combines the label and data
1252 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001253
1254 @retval QCBOR_ERR_UNSUPPORTED
1255
1256 @retval QCBOR_ERR_HIT_END
1257
1258 @retval QCBOR_ERR_INT_OVERFLOW
1259
1260 @retval QCBOR_ERR_STRING_ALLOCATE
1261
1262 @retval QCBOR_ERR_STRING_TOO_LONG
1263
1264 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1265
1266 @retval QCBOR_ERR_BAD_TYPE_7
1267
1268 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1269
1270 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1271
1272 @retval QCBOR_ERR_TOO_MANY_TAGS
1273
1274 @retval QCBOR_ERR_MAP_LABEL_TYPE
1275
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001276 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001277 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001278static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001279GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001280{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001281 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001283 if(nReturn)
1284 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001285
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001286 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001287 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001288 goto Done;
1289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001290
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001291 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1292 // In a map and caller wants maps decoded, not treated as arrays
1293
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001294 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001295 // If in a map and the right decoding mode, get the label
1296
Laurence Lundbladeee851742020-01-08 08:37:05 -08001297 // Save label in pDecodedItem and get the next which will
1298 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001299 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001300 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001301 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001302 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001303 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301305 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001306
1307 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1308 // strings are always good labels
1309 pDecodedItem->label.string = LabelItem.val.string;
1310 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1311 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001312 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001313 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1314 goto Done;
1315 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1316 pDecodedItem->label.int64 = LabelItem.val.int64;
1317 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1318 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1319 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1320 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1321 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1322 pDecodedItem->label.string = LabelItem.val.string;
1323 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1324 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1325 } else {
1326 // label is not an int or a string. It is an arrray
1327 // or a float or such and this implementation doesn't handle that.
1328 // Also, tags on labels are ignored.
1329 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1330 goto Done;
1331 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001332 }
1333 } else {
1334 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001335 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001336 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001337 goto Done;
1338 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001339 // Decoding a map as an array
1340 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001341 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1342 // Cast is needed because of integer promotion
1343 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001344 }
1345 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001346
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001347Done:
1348 return nReturn;
1349}
1350
1351
Laurence Lundblade02625d42020-06-25 14:41:41 -07001352/*
1353 See if next item is a CBOR break. If it is, it is consumed,
1354 if not it is not consumed.
1355*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001356static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001357NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1358{
1359 *pbNextIsBreak = false;
1360 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001361 QCBORItem Peek;
1362 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1363 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1364 if(uReturn != QCBOR_SUCCESS) {
1365 return uReturn;
1366 }
1367 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001368 // It is not a break, rewind so it can be processed normally.
1369 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001370 } else {
1371 *pbNextIsBreak = true;
1372 }
1373 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001374
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001375 return QCBOR_SUCCESS;
1376}
1377
1378
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001379/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001380 An item was just consumed, now figure out if it was the
1381 end of an array or map that can be closed out. That
1382 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001383*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001384static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001385{
1386 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001387
Laurence Lundblade642282a2020-06-23 12:00:33 -07001388 /* This loops ascending nesting levels as long as there is ascending to do */
1389 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1390
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001391 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001392 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001393 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1394 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001395 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 break;
1397 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001398 /* All of a definite length array was consumed; fall through to
1399 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001401 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001402 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001403 bool bIsBreak = false;
1404 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1405 if(uReturn != QCBOR_SUCCESS) {
1406 goto Done;
1407 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408
1409 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001410 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001411 break;
1412 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001413
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001414 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001415 /*
1416 Break occurred inside a bstr-wrapped CBOR or
1417 in the top level sequence. This is always an
1418 error because neither are an indefinte length
1419 map/array.
1420 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421 uReturn = QCBOR_ERR_BAD_BREAK;
1422 goto Done;
1423 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001424
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001426 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427
Laurence Lundblade02625d42020-06-25 14:41:41 -07001428 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001429
Laurence Lundblade93d89472020-10-03 22:30:50 -07001430 /* But ascent in bounded mode is only by explicit call to
1431 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001432 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001433 /* Set the count to zero for definite length arrays to indicate
1434 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001435 if(bMarkEnd) {
1436 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001437 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001438
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001439 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001440 break;
1441 }
1442
1443 /* Finally, actually ascend one level. */
1444 DecodeNesting_Ascend(&(pMe->nesting));
1445 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001447 uReturn = QCBOR_SUCCESS;
1448
1449Done:
1450 return uReturn;
1451}
1452
1453
1454/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001455 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1457 indefinte length maps and arrays by looking at the item count or
1458 finding CBOR breaks. It detects the ends of the top-level sequence
1459 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001460
1461 @retval QCBOR_ERR_UNSUPPORTED X
1462
1463 @retval QCBOR_ERR_HIT_END
1464
1465 @retval QCBOR_ERR_INT_OVERFLOW X
1466
1467 @retval QCBOR_ERR_STRING_ALLOCATE
1468
1469 @retval QCBOR_ERR_STRING_TOO_LONG
1470
1471 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1472
1473 @retval QCBOR_ERR_BAD_TYPE_7 X
1474
1475 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1476
1477 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1478
1479 @retval QCBOR_ERR_TOO_MANY_TAGS
1480
1481 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1482
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001483 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001484
1485 @retval QCBOR_ERR_NO_MORE_ITEMS
1486
1487 @retval QCBOR_ERR_BAD_BREAK
1488
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001489 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001490static QCBORError
1491QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001492{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001493 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001494 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001495
Laurence Lundblade642282a2020-06-23 12:00:33 -07001496 /*
1497 If out of bytes to consume, it is either the end of the top-level
1498 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001499
Laurence Lundblade642282a2020-06-23 12:00:33 -07001500 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1501 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1502 CBOR is exited, the length is set back to the top-level's length
1503 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001504 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001505 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001506 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001507 goto Done;
1508 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001509
Laurence Lundblade642282a2020-06-23 12:00:33 -07001510 /*
1511 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001512 array. The check for the end of an indefinite length array is
1513 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001514 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001515 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001516 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001517 goto Done;
1518 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001519
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001520 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001521 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001522 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1523 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001524 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001525 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301526
Laurence Lundblade642282a2020-06-23 12:00:33 -07001527 /*
1528 Breaks ending arrays/maps are always processed at the end of this
1529 function. They should never show up here.
1530 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301531 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001532 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301533 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301534 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade642282a2020-06-23 12:00:33 -07001536 /*
1537 Record the nesting level for this data item before processing any
1538 of decrementing and descending.
1539 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001540 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001541
Laurence Lundblade642282a2020-06-23 12:00:33 -07001542
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001543 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001544 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001545 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001546 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001547
Laurence Lundblade93d89472020-10-03 22:30:50 -07001548 Empty indefinite length maps and arrays are descended into, but
1549 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001550
1551 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001552 encloses them so a decrement needs to be done for them too, but
1553 that is done only when all the items in them have been
1554 processed, not when they are opened with the exception of an
1555 empty map or array.
1556 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001557 QCBORError uDescendErr;
1558 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001559 pDecodedItem->uDataType,
1560 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001561 if(uDescendErr != QCBOR_SUCCESS) {
1562 /* This error is probably a traversal error and it
1563 overrides the non-traversal error. */
1564 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001565 goto Done;
1566 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001567 }
1568
Laurence Lundblade02625d42020-06-25 14:41:41 -07001569 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1570 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1571 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001572 /*
1573 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001574 - A non-aggregate like an integer or string
1575 - An empty definite length map or array
1576 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001577
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001578 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001579 definite length map/array and break detection for an indefinite
1580 length map/array. If the end of the map/array was reached, then
1581 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001582 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001583 QCBORError uAscendErr;
1584 uAscendErr = NestLevelAscender(me, true);
1585 if(uAscendErr != QCBOR_SUCCESS) {
1586 /* This error is probably a traversal error and it
1587 overrides the non-traversal error. */
1588 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001589 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001590 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301591 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001592
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001593 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001594 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001595 Tell the caller what level is next. This tells them what
1596 maps/arrays were closed out and makes it possible for them to
1597 reconstruct the tree with just the information returned in
1598 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001599 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001600 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001601 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001602 pDecodedItem->uNextNestLevel = 0;
1603 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001604 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001605 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001606
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001607Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001608 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001609}
1610
Laurence Lundblade9b334962020-08-27 10:55:53 -07001611static void ShiftTags(QCBORItem *pDecodedItem)
1612{
1613 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1614 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1615 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1616 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1617}
1618
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001619
Laurence Lundblade59289e52019-12-30 13:44:37 -08001620/*
1621 Mostly just assign the right data type for the date string.
1622 */
1623inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1624{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001625 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1626 return QCBOR_ERR_BAD_OPT_TAG;
1627 }
1628
1629 const UsefulBufC Temp = pDecodedItem->val.string;
1630 pDecodedItem->val.dateString = Temp;
1631 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001632 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001633 return QCBOR_SUCCESS;
1634}
1635
1636
Laurence Lundblade9b334962020-08-27 10:55:53 -07001637
Laurence Lundblade59289e52019-12-30 13:44:37 -08001638/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001639 The epoch formatted date. Turns lots of different forms of encoding
1640 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001641 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001642static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001643{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001644 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001645
1646 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1647
1648 switch (pDecodedItem->uDataType) {
1649
1650 case QCBOR_TYPE_INT64:
1651 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1652 break;
1653
1654 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001655 // This only happens for CBOR type 0 > INT64_MAX so it is
1656 // always an overflow.
1657 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1658 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001659 break;
1660
1661 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001662 case QCBOR_TYPE_FLOAT:
1663#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001664 {
1665 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001666 // conversion to an int64_t to be able to detect doubles that
1667 // are too large to fit into an int64_t. A double has 52
1668 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1669 // to a double actually causes a round up which is bad and
1670 // wrong for the comparison because it will allow conversion
1671 // of doubles that can't fit into a uint64_t. To remedy this
1672 // INT64_MAX - 0x7ff is used as the cutoff point because if
1673 // that value rounds up in conversion to double it will still
1674 // be less than INT64_MAX. 0x7ff is picked because it has 11
1675 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001677 // INT64_MAX seconds is on the order of 10 billion years, and
1678 // the earth is less than 5 billion years old, so for most
1679 // uses this conversion error won't occur even though doubles
1680 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001681 //
1682 // Without the 0x7ff there is a ~30 minute range of time
1683 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001684 // where this code would go wrong. Some compilers
1685 // will generate warnings or errors without the 0x7ff
1686 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001687 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1688 pDecodedItem->val.dfnum :
1689 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001690 if(isnan(d) ||
1691 d > (double)(INT64_MAX - 0x7ff) ||
1692 d < (double)(INT64_MIN + 0x7ff)) {
1693 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694 goto Done;
1695 }
1696 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001697 pDecodedItem->val.epochDate.fSecondsFraction =
1698 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001699 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001700#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001701
Laurence Lundbladec7114722020-08-13 05:11:40 -07001702 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001703 goto Done;
1704
Laurence Lundblade9682a532020-06-06 18:33:04 -07001705#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001706 break;
1707
1708 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001709 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710 goto Done;
1711 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001712
Laurence Lundblade59289e52019-12-30 13:44:37 -08001713 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1714
1715Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001716 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001717}
1718
1719
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001720/*
1721 Mostly just assign the right data type for the bignum.
1722 */
1723inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1724{
1725 // Stack Use: UsefulBuf 1 -- 16
1726 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1727 return QCBOR_ERR_BAD_OPT_TAG;
1728 }
1729 const UsefulBufC Temp = pDecodedItem->val.string;
1730 pDecodedItem->val.bigNum = Temp;
1731 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1732 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1733 : QCBOR_TYPE_NEGBIGNUM);
1734 return QCBOR_SUCCESS;
1735}
1736
1737
Laurence Lundblade59289e52019-12-30 13:44:37 -08001738#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1739/*
1740 Decode decimal fractions and big floats.
1741
1742 When called pDecodedItem must be the array that is tagged as a big
1743 float or decimal fraction, the array that has the two members, the
1744 exponent and mantissa.
1745
1746 This will fetch and decode the exponent and mantissa and put the
1747 result back into pDecodedItem.
1748 */
1749inline static QCBORError
1750QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1751{
1752 QCBORError nReturn;
1753
1754 // --- Make sure it is an array; track nesting level of members ---
1755 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1756 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1757 goto Done;
1758 }
1759
1760 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001761 // definite length arrays, but not for indefnite. Instead remember
1762 // the nesting level the two integers must be at, which is one
1763 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1765
1766 // --- Is it a decimal fraction or a bigfloat? ---
1767 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1768 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1769
1770 // --- Get the exponent ---
1771 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001772 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001773 if(nReturn != QCBOR_SUCCESS) {
1774 goto Done;
1775 }
1776 if(exponentItem.uNestingLevel != nNestLevel) {
1777 // Array is empty or a map/array encountered when expecting an int
1778 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1779 goto Done;
1780 }
1781 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1782 // Data arriving as an unsigned int < INT64_MAX has been converted
1783 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1784 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1785 // will be too large for this to handle and thus an error that will
1786 // get handled in the next else.
1787 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1788 } else {
1789 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1790 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1791 goto Done;
1792 }
1793
1794 // --- Get the mantissa ---
1795 QCBORItem mantissaItem;
1796 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1797 if(nReturn != QCBOR_SUCCESS) {
1798 goto Done;
1799 }
1800 if(mantissaItem.uNestingLevel != nNestLevel) {
1801 // Mantissa missing or map/array encountered when expecting number
1802 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1803 goto Done;
1804 }
1805 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1806 // Data arriving as an unsigned int < INT64_MAX has been converted
1807 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1808 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1809 // will be too large for this to handle and thus an error that
1810 // will get handled in an else below.
1811 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001812 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1813 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814 // Got a good big num mantissa
1815 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1816 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001817 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1818 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1819 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001820 } else {
1821 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1822 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1823 goto Done;
1824 }
1825
1826 // --- Check that array only has the two numbers ---
1827 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001828 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001832 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833
1834Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 return nReturn;
1836}
1837#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1838
1839
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001840inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1841{
1842 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1843 return QCBOR_ERR_BAD_OPT_TAG;
1844 }
1845 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1846 return QCBOR_SUCCESS;
1847}
1848
1849
1850inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1851{
1852 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1853 return QCBOR_ERR_BAD_OPT_TAG;
1854 }
1855 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001856
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001857 return QCBOR_SUCCESS;
1858}
1859
1860
1861inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1862{
1863 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1864 return QCBOR_ERR_BAD_OPT_TAG;
1865 }
1866 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001867
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001868 return QCBOR_SUCCESS;
1869}
1870
1871
1872inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1873{
1874 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1875 return QCBOR_ERR_BAD_OPT_TAG;
1876 }
1877 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001878
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001879 return QCBOR_SUCCESS;
1880}
1881
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001882
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001883inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1884{
1885 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1886 return QCBOR_ERR_BAD_OPT_TAG;
1887 }
1888 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001889
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001890 return QCBOR_SUCCESS;
1891}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001892
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001893
1894inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1895{
1896 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1897 return QCBOR_ERR_BAD_OPT_TAG;
1898 }
1899 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001900
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001901 return QCBOR_SUCCESS;
1902}
1903
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001904
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001905inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1906{
1907 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1908 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001909 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001910 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1911 } else {
1912 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001913
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001915
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001916 return QCBOR_SUCCESS;
1917}
1918
1919
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001920inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1921{
1922 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1923 return QCBOR_ERR_BAD_OPT_TAG;
1924 }
1925 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001926
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001927 return QCBOR_SUCCESS;
1928}
1929
1930
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001932 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001933 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001934static QCBORError
1935QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001936{
1937 QCBORError nReturn;
1938
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001939 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001940 if(nReturn != QCBOR_SUCCESS) {
1941 goto Done;
1942 }
1943
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001944 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001945 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001947 // Many of the functions here only just map a CBOR tag to
1948 // a QCBOR_TYPE for a string and could probably be
1949 // implemented with less object code. This implementation
1950 // of string types takes about 120 bytes of object code
1951 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001952 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001953 nReturn = DecodeDateString(pDecodedItem);
1954 break;
1955
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001956 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957 nReturn = DecodeDateEpoch(pDecodedItem);
1958 break;
1959
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001960 case CBOR_TAG_POS_BIGNUM:
1961 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 nReturn = DecodeBigNum(pDecodedItem);
1963 break;
1964
Laurence Lundblade93d89472020-10-03 22:30:50 -07001965#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001966 case CBOR_TAG_DECIMAL_FRACTION:
1967 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 // For aggregate tagged types, what goes into pTags is only collected
1969 // from the surrounding data item, not the contents, so pTags is not
1970 // passed on here.
1971
1972 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1973 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001974#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001975
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001976 case CBOR_TAG_CBOR:
1977 nReturn = DecodeWrappedCBOR(pDecodedItem);
1978 break;
1979
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001980 case CBOR_TAG_CBOR_SEQUENCE:
1981 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1982 break;
1983
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001984 case CBOR_TAG_URI:
1985 nReturn = DecodeURI(pDecodedItem);
1986 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001987
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001988 case CBOR_TAG_B64URL:
1989 nReturn = DecodeB64URL(pDecodedItem);
1990 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001991
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001992 case CBOR_TAG_B64:
1993 nReturn = DecodeB64(pDecodedItem);
1994 break;
1995
1996 case CBOR_TAG_MIME:
1997 case CBOR_TAG_BINARY_MIME:
1998 nReturn = DecodeMIME(pDecodedItem);
1999 break;
2000
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002001 case CBOR_TAG_REGEX:
2002 nReturn = DecodeRegex(pDecodedItem);
2003 break;
2004
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002005 case CBOR_TAG_BIN_UUID:
2006 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002007 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002008
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002009 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002010 // The end of the tag list or no tags
2011 // Successful exit from the loop.
2012 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002013
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002014 default:
2015 // A tag that is not understood
2016 // A successful exit from the loop
2017 goto Done;
2018
2019 }
2020 if(nReturn != QCBOR_SUCCESS) {
2021 goto Done;
2022 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002023 // A tag was successfully processed, shift it
2024 // out of the list of tags returned.
2025 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 }
2027
2028Done:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002029 return nReturn;
2030}
2031
2032
2033QCBORError
2034QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2035{
2036 QCBORError uErr;
2037 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2038 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2040 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2041 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002042 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043}
2044
2045
2046/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002047 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002049void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2050{
2051 if(pMe->uLastError != QCBOR_SUCCESS) {
2052 return;
2053 }
2054
2055 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2056}
2057
2058
2059/*
2060 Public function, see header qcbor/qcbor_decode.h file
2061 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002062QCBORError
2063QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2064 QCBORItem *pDecodedItem,
2065 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002066{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002067 QCBORError nReturn;
2068
2069 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2070 if(nReturn != QCBOR_SUCCESS) {
2071 return nReturn;
2072 }
2073
2074 if(pTags != NULL) {
2075 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002076 // Reverse the order because pTags is reverse of
2077 // QCBORItem.uTags.
2078 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002079 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002080 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002081 }
2082 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2083 return QCBOR_ERR_TOO_MANY_TAGS;
2084 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07002085 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[i]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002086 pTags->uNumUsed++;
2087 }
2088 }
2089
2090 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002091}
2092
2093
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002094/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302095 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302096 next one down. If a layer has no work to do for a particular item
2097 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002098
Laurence Lundblade59289e52019-12-30 13:44:37 -08002099 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2100 tagged data items, turning them into the local C representation.
2101 For the most simple it is just associating a QCBOR_TYPE with the data. For
2102 the complex ones that an aggregate of data items, there is some further
2103 decoding and a little bit of recursion.
2104
2105 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302106 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302107 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002108 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002109
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302110 - GetNext_MapEntry -- This handles the combining of two
2111 items, the label and the data, that make up a map entry.
2112 It only does work on maps. It combines the label and data
2113 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundblade59289e52019-12-30 13:44:37 -08002115 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2116 tags into bit flags associated with the data item. No actual decoding
2117 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002118
Laurence Lundblade59289e52019-12-30 13:44:37 -08002119 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302120 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302121 string allocater to create contiguous space for the item. It
2122 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002123
Laurence Lundblade59289e52019-12-30 13:44:37 -08002124 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2125 atomic data item has a "major type", an integer "argument" and optionally
2126 some content. For text and byte strings, the content is the bytes
2127 that make up the string. These are the smallest data items that are
2128 considered to be well-formed. The content may also be other data items in
2129 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002130
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002131 Roughly this takes 300 bytes of stack for vars. Need to
2132 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002133
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302134 */
2135
2136
2137/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002138 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002139 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002140bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002141 const QCBORItem *pItem,
2142 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002143{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002144 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002145 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002146 break;
2147 }
2148 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002149 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002150 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002151 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002152
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002153 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002154}
2155
2156
2157/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002158 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002159 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002160QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002161{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002162 QCBORError uReturn = me->uLastError;
2163
2164 if(uReturn != QCBOR_SUCCESS) {
2165 goto Done;
2166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002167
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002168 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002169 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002170 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002171 goto Done;
2172 }
2173
2174 // Error out if not all the bytes are consumed
2175 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002176 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002178
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002179Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302180 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002181 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002182 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002183
Laurence Lundblade085d7952020-07-24 10:26:30 -07002184 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002185}
2186
2187
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002188/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002189 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002190*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002191// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002192uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2193 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002194 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002195{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002196 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2197 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002198 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002199 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002200 }
2201}
2202
Laurence Lundblade9b334962020-08-27 10:55:53 -07002203/*
2204 Public function, see header qcbor/qcbor_decode.h file
2205*/
2206uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2207 uint32_t uIndex)
2208{
2209 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2210 return CBOR_TAG_INVALID64;
2211 } else {
2212 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2213 }
2214}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002215
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002216/*
2217
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002218Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002219
Laurence Lundbladeee851742020-01-08 08:37:05 -08002220 - Hit end of input before it was expected while decoding type and
2221 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002223 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundbladeee851742020-01-08 08:37:05 -08002225 - Hit end of input while decoding a text or byte string
2226 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundbladeee851742020-01-08 08:37:05 -08002228 - Encountered conflicting tags -- e.g., an item is tagged both a date
2229 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002230
Laurence Lundbladeee851742020-01-08 08:37:05 -08002231 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002232 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladeee851742020-01-08 08:37:05 -08002234 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002235 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002236
Laurence Lundbladeee851742020-01-08 08:37:05 -08002237 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2238 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundbladeee851742020-01-08 08:37:05 -08002240 - The type of a map label is not a string or int
2241 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002243 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002245 */
2246
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002247
2248
Laurence Lundbladef6531662018-12-04 10:42:22 +09002249
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002250/* ===========================================================================
2251 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002252
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002253 This implements a simple sting allocator for indefinite length
2254 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2255 implements the function type QCBORStringAllocate and allows easy
2256 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002257
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002258 This particular allocator is built-in for convenience. The caller
2259 can implement their own. All of this following code will get
2260 dead-stripped if QCBORDecode_SetMemPool() is not called.
2261
2262 This is a very primitive memory allocator. It does not track
2263 individual allocations, only a high-water mark. A free or
2264 reallocation must be of the last chunk allocated.
2265
2266 The size of the pool and offset to free memory are packed into the
2267 first 8 bytes of the memory pool so we don't have to keep them in
2268 the decode context. Since the address of the pool may not be
2269 aligned, they have to be packed and unpacked as if they were
2270 serialized data of the wire or such.
2271
2272 The sizes packed in are uint32_t to be the same on all CPU types
2273 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002274 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002275
2276
Laurence Lundbladeee851742020-01-08 08:37:05 -08002277static inline int
2278MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002279{
2280 // Use of UsefulInputBuf is overkill, but it is convenient.
2281 UsefulInputBuf UIB;
2282
Laurence Lundbladeee851742020-01-08 08:37:05 -08002283 // Just assume the size here. It was checked during SetUp so
2284 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002285 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002286 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2287 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2288 return UsefulInputBuf_GetError(&UIB);
2289}
2290
2291
Laurence Lundbladeee851742020-01-08 08:37:05 -08002292static inline int
2293MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002294{
2295 // Use of UsefulOutBuf is overkill, but convenient. The
2296 // length check performed here is useful.
2297 UsefulOutBuf UOB;
2298
2299 UsefulOutBuf_Init(&UOB, Pool);
2300 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2301 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2302 return UsefulOutBuf_GetError(&UOB);
2303}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002304
2305
2306/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002307 Internal function for an allocation, reallocation free and destuct.
2308
2309 Having only one function rather than one each per mode saves space in
2310 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002311
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002312 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2313 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002314static UsefulBuf
2315MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002316{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002317 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002318
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002319 uint32_t uPoolSize;
2320 uint32_t uFreeOffset;
2321
2322 if(uNewSize > UINT32_MAX) {
2323 // This allocator is only good up to 4GB. This check should
2324 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2325 goto Done;
2326 }
2327 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2328
2329 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2330 goto Done;
2331 }
2332
2333 if(uNewSize) {
2334 if(pMem) {
2335 // REALLOCATION MODE
2336 // Calculate pointer to the end of the memory pool. It is
2337 // assumed that pPool + uPoolSize won't wrap around by
2338 // assuming the caller won't pass a pool buffer in that is
2339 // not in legitimate memory space.
2340 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2341
2342 // Check that the pointer for reallocation is in the range of the
2343 // pool. This also makes sure that pointer math further down
2344 // doesn't wrap under or over.
2345 if(pMem >= pPool && pMem < pPoolEnd) {
2346 // Offset to start of chunk for reallocation. This won't
2347 // wrap under because of check that pMem >= pPool. Cast
2348 // is safe because the pool is always less than UINT32_MAX
2349 // because of check in QCBORDecode_SetMemPool().
2350 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2351
2352 // Check to see if the allocation will fit. uPoolSize -
2353 // uMemOffset will not wrap under because of check that
2354 // pMem is in the range of the uPoolSize by check above.
2355 if(uNewSize <= uPoolSize - uMemOffset) {
2356 ReturnValue.ptr = pMem;
2357 ReturnValue.len = uNewSize;
2358
2359 // Addition won't wrap around over because uNewSize was
2360 // checked to be sure it is less than the pool size.
2361 uFreeOffset = uMemOffset + uNewSize32;
2362 }
2363 }
2364 } else {
2365 // ALLOCATION MODE
2366 // uPoolSize - uFreeOffset will not underflow because this
2367 // pool implementation makes sure uFreeOffset is always
2368 // smaller than uPoolSize through this check here and
2369 // reallocation case.
2370 if(uNewSize <= uPoolSize - uFreeOffset) {
2371 ReturnValue.len = uNewSize;
2372 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002373 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002374 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002375 }
2376 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002377 if(pMem) {
2378 // FREE MODE
2379 // Cast is safe because of limit on pool size in
2380 // QCBORDecode_SetMemPool()
2381 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2382 } else {
2383 // DESTRUCT MODE
2384 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002385 }
2386 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002387
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002388 UsefulBuf Pool = {pPool, uPoolSize};
2389 MemPool_Pack(Pool, uFreeOffset);
2390
2391Done:
2392 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002393}
2394
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002395
Laurence Lundbladef6531662018-12-04 10:42:22 +09002396/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002397 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002398 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002399QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2400 UsefulBuf Pool,
2401 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002402{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002403 // The pool size and free mem offset are packed into the beginning
2404 // of the pool memory. This compile time check make sure the
2405 // constant in the header is correct. This check should optimize
2406 // down to nothing.
2407 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002408 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002410
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002411 // The pool size and free offset packed in to the beginning of pool
2412 // memory are only 32-bits. This check will optimize out on 32-bit
2413 // machines.
2414 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002415 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002416 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002417
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002418 // This checks that the pool buffer given is big enough.
2419 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002420 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002422
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002423 pMe->StringAllocator.pfAllocator = MemPool_Function;
2424 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2425 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002426
Laurence Lundblade30816f22018-11-10 13:40:22 +07002427 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002428}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002429
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002430
2431
Laurence Lundblade9b334962020-08-27 10:55:53 -07002432static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2433{
2434 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2435}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002436
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002437
2438/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002439 Consume an entire map or array (and do next to
2440 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002441 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002442static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002443ConsumeItem(QCBORDecodeContext *pMe,
2444 const QCBORItem *pItemToConsume,
2445 uint_fast8_t *puNextNestLevel)
2446{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002447 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002448 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002449
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002450 // If it is a map or array, this will tell if it is empty.
2451 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2452
2453 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2454 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002455
Laurence Lundblade1341c592020-04-11 14:19:05 -07002456 /* This works for definite and indefinite length
2457 * maps and arrays by using the nesting level
2458 */
2459 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002460 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002461 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002462 goto Done;
2463 }
2464 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002465
Laurence Lundblade1341c592020-04-11 14:19:05 -07002466 if(puNextNestLevel != NULL) {
2467 *puNextNestLevel = Item.uNextNestLevel;
2468 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002469 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002470
Laurence Lundblade1341c592020-04-11 14:19:05 -07002471 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002472 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002473 if(puNextNestLevel != NULL) {
2474 /* Just pass the nesting level through */
2475 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2476 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002477 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002478 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002479
2480Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002481 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002482}
2483
2484
Laurence Lundblade1341c592020-04-11 14:19:05 -07002485/* Return true if the labels in Item1 and Item2 are the same.
2486 Works only for integer and string labels. Returns false
2487 for any other type. */
2488static inline bool
2489MatchLabel(QCBORItem Item1, QCBORItem Item2)
2490{
2491 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2492 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2493 return true;
2494 }
2495 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002496 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002497 return true;
2498 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002499 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002500 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2501 return true;
2502 }
2503 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2504 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2505 return true;
2506 }
2507 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002508
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 /* Other label types are never matched */
2510 return false;
2511}
2512
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002513
2514/*
2515 Returns true if Item1 and Item2 are the same type
2516 or if either are of QCBOR_TYPE_ANY.
2517 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002518static inline bool
2519MatchType(QCBORItem Item1, QCBORItem Item2)
2520{
2521 if(Item1.uDataType == Item2.uDataType) {
2522 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002523 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002524 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002525 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002526 return true;
2527 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002528 return false;
2529}
2530
2531
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002532/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002533 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002534
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002535 @param[in] pMe The decode context to search.
2536 @param[in,out] pItemArray The items to search for and the items found.
2537 @param[out] puOffset Byte offset of last item matched.
2538 @param[in] pCBContext Context for the not-found item call back.
2539 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002540
2541 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2542
Laurence Lundblade93d89472020-10-03 22:30:50 -07002543 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2544 were found for one of the labels being
2545 search for. This duplicate detection is
2546 only performed for items in pItemArray,
2547 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002548
Laurence Lundblade93d89472020-10-03 22:30:50 -07002549 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2550 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002551
2552 @retval Also errors returned by QCBORDecode_GetNext().
2553
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002554 On input pItemArray contains a list of labels and data types
2555 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002556
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002557 On output the fully retrieved items are filled in with
2558 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002559
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002560 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002561 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002562// TODO: make this handle indefinite length strings, possibly with
2563// allocation only when returning the string.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002564static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002565MapSearch(QCBORDecodeContext *pMe,
2566 QCBORItem *pItemArray,
2567 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002568 void *pCBContext,
2569 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002570{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002571 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002572 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002573
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002574 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002575 uReturn = pMe->uLastError;
2576 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002577 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002578
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002579 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002580 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2581 /* QCBOR_TYPE_NONE as first item indicates just looking
2582 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002583 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2584 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002585 }
2586
Laurence Lundblade085d7952020-07-24 10:26:30 -07002587 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2588 // It is an empty bounded array or map
2589 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2590 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002591 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002592 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002593 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002594 // Nothing is ever found in an empty array or map. All items
2595 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002596 uReturn = QCBOR_SUCCESS;
2597 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002598 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002599 }
2600
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002601 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002602 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2603
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002604 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002605 UsefulInputBuf_Seek(&(pMe->InBuf),
2606 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002607
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002608 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002609 Loop over all the items in the map or array. Each item
2610 could be a map or array, but label matching is only at
2611 the main level. This handles definite and indefinite
2612 length maps and arrays. The only reason this is ever
2613 called on arrays is to find their end position.
2614
2615 This will always run over all items in order to do
2616 duplicate detection.
2617
2618 This will exit with failure if it encounters an
2619 unrecoverable error, but continue on for recoverable
2620 errors.
2621
2622 If a recoverable error occurs on a matched item, then
2623 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002624 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002625 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002626 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002627 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002628 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002629 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002630
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002631 /* Get the item */
2632 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002633 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2634 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002635 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002636 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002637 goto Done;
2638 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002639 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002640 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002641 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002642 goto Done;
2643 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002644
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002645 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002646 bool bMatched = false;
2647 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2648 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002649 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002650 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2651 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002652 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002653 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002654 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002655 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002656 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002657 goto Done;
2658 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002659
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002660 if(uResult != QCBOR_SUCCESS) {
2661 uReturn = uResult;
2662 goto Done;
2663 }
2664
Laurence Lundblade1341c592020-04-11 14:19:05 -07002665 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002666 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002667 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002668 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002669 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002670 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002671 bMatched = true;
2672 }
2673 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002674
2675
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002676 if(!bMatched && pfCallback != NULL) {
2677 /*
2678 Call the callback on unmatched labels.
2679 (It is tempting to do duplicate detection here, but that would
2680 require dynamic memory allocation because the number of labels
2681 that might be encountered is unbounded.)
2682 */
2683 uReturn = (*pfCallback)(pCBContext, &Item);
2684 if(uReturn != QCBOR_SUCCESS) {
2685 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 }
2687 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002688
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002689 /*
2690 Consume the item whether matched or not. This
2691 does the work of traversing maps and array and
2692 everything in them. In this loop only the
2693 items at the current nesting level are examined
2694 to match the labels.
2695 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002696 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002697 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002698 goto Done;
2699 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002700
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002701 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002702
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002703 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002704
2705 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002706
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002707 // Check here makes sure that this won't accidentally be
2708 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002709 // QCBOR_MAX_DECODE_INPUT_SIZE.
2710 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2711 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2712 goto Done;
2713 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002714 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2715 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002716
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002717 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002718 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2719
2720 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002721 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002722 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002723 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002724 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2725 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002726 }
2727 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002728
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002729 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002730}
2731
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002732
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002733/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002734 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002735*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002736void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2737 int64_t nLabel,
2738 uint8_t uQcborType,
2739 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002740{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002741 if(pMe->uLastError != QCBOR_SUCCESS) {
2742 return;
2743 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002744
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002745 QCBORItem OneItemSeach[2];
2746 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2747 OneItemSeach[0].label.int64 = nLabel;
2748 OneItemSeach[0].uDataType = uQcborType;
2749 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002750
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002751 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002752
2753 *pItem = OneItemSeach[0];
2754
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002755 if(uReturn != QCBOR_SUCCESS) {
2756 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002757 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002758 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002759 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002760 }
2761
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002762 Done:
2763 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002764}
2765
2766
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002767/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002768 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002769*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002770void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2771 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002772 uint8_t uQcborType,
2773 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002774{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002775 if(pMe->uLastError != QCBOR_SUCCESS) {
2776 return;
2777 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002779 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002780 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2781 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2782 OneItemSeach[0].uDataType = uQcborType;
2783 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002784
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002785 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2786 if(uReturn != QCBOR_SUCCESS) {
2787 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002788 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002789 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002790 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002791 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002792 }
2793
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002794 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002795
2796Done:
2797 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002798}
2799
2800
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002801
Laurence Lundblade93d89472020-10-03 22:30:50 -07002802static QCBORError
2803CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002804{
2805 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2806 if(uDataType == puTypeList[i]) {
2807 return QCBOR_SUCCESS;
2808 }
2809 }
2810 return QCBOR_ERR_UNEXPECTED_TYPE;
2811}
2812
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002813
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002814/**
2815 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002816 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002817
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002818 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2819 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002820
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002821 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2822 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002823static QCBORError
2824CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002825{
2826 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2827 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2828 /* There are tags that QCBOR couldn't process on this item and
2829 the caller has told us there should not be. */
2830 return QCBOR_ERR_UNEXPECTED_TYPE;
2831 }
2832
2833 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2834 const int nItemType = pItem->uDataType;
2835
2836 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2837 // Must match the tag and only the tag
2838 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2839 }
2840
2841 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2842 if(uReturn == QCBOR_SUCCESS) {
2843 return QCBOR_SUCCESS;
2844 }
2845
2846 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2847 /* Must match the content type and only the content type.
2848 There was no match just above so it is a fail. */
2849 return QCBOR_ERR_UNEXPECTED_TYPE;
2850 }
2851
2852 /* If here it can match either the tag or the content
2853 and it hasn't matched the content, so the end
2854 result is whether it matches the tag. This is
2855 also the case that the CBOR standard discourages. */
2856
2857 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2858}
2859
Laurence Lundblade9b334962020-08-27 10:55:53 -07002860
Laurence Lundblade9b334962020-08-27 10:55:53 -07002861
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002862// This could be semi-private if need be
2863static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002864void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2865 int64_t nLabel,
2866 TagSpecification TagSpec,
2867 QCBORItem *pItem)
2868{
2869 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2870 if(pMe->uLastError != QCBOR_SUCCESS) {
2871 return;
2872 }
2873
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002874 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002875}
2876
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002877
2878// This could be semi-private if need be
2879static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002880void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2881 const char *szLabel,
2882 TagSpecification TagSpec,
2883 QCBORItem *pItem)
2884{
2885 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2886 if(pMe->uLastError != QCBOR_SUCCESS) {
2887 return;
2888 }
2889
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002890 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002891}
2892
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002893// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002894void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2895 int64_t nLabel,
2896 TagSpecification TagSpec,
2897 UsefulBufC *pString)
2898{
2899 QCBORItem Item;
2900 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2901 if(pMe->uLastError == QCBOR_SUCCESS) {
2902 *pString = Item.val.string;
2903 }
2904}
2905
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002906// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002907void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2908 const char * szLabel,
2909 TagSpecification TagSpec,
2910 UsefulBufC *pString)
2911{
2912 QCBORItem Item;
2913 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2914 if(pMe->uLastError == QCBOR_SUCCESS) {
2915 *pString = Item.val.string;
2916 }
2917}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002918
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002919/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002920 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002921*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002922void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002923{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002924 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2925 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002926}
2927
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002928/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002929 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002930*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002931void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2932 QCBORItem *pItemList,
2933 void *pCallbackCtx,
2934 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002935{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002936 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2937 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002938}
2939
2940
Laurence Lundblade34691b92020-05-18 22:25:25 -07002941static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002942{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002943 // The first item in pSearch is the one that is to be
2944 // entered. It should be the only one filled in. Any other
2945 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002946 if(pMe->uLastError != QCBOR_SUCCESS) {
2947 // Already in error state; do nothing.
2948 return;
2949 }
2950
2951 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002952 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002953 if(pMe->uLastError != QCBOR_SUCCESS) {
2954 return;
2955 }
2956
Laurence Lundblade9b334962020-08-27 10:55:53 -07002957 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002958 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002959 return;
2960 }
2961
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002962 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002963 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002964
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002965 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002966 be at the right place.
2967
2968 The UsefulInBuf offset could be anywhere, so no assumption is
2969 made about it.
2970
2971 No assumption is made about the pre-order nesting level either.
2972
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002973 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002974 the map level that is being entered.
2975 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002976 /* Seek to the data item that is the map or array */
2977 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002978
2979 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002980
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002981 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002982}
2983
2984
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002985/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002986 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002987*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002988void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002989{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002990 QCBORItem OneItemSeach[2];
2991 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2992 OneItemSeach[0].label.int64 = nLabel;
2993 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2994 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002995
Laurence Lundblade9b334962020-08-27 10:55:53 -07002996 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002997 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002998}
2999
3000
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003001/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003002 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003003*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003004void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003005{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003006 QCBORItem OneItemSeach[2];
3007 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3008 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3009 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3010 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003011
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003012 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003013}
3014
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003015/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003016 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003017*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003018void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003019{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003020 QCBORItem OneItemSeach[2];
3021 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3022 OneItemSeach[0].label.int64 = nLabel;
3023 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3024 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003025
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003026 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003027}
3028
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003029/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003030 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003031*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003032void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3033{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003034 QCBORItem OneItemSeach[2];
3035 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3036 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3037 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3038 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003039
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003040 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003041}
3042
3043
Laurence Lundblade02625d42020-06-25 14:41:41 -07003044// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003045void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003046{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003047 QCBORError uErr;
3048
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003049 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003050 if(pMe->uLastError != QCBOR_SUCCESS) {
3051 // Already in error state; do nothing.
3052 return;
3053 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003054
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003055 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003056 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003057 uErr = QCBORDecode_GetNext(pMe, &Item);
3058 if(uErr != QCBOR_SUCCESS) {
3059 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003060 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003061 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003062 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3063 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003064 }
3065
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003066 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003067
3068
Laurence Lundbladef0499502020-08-01 11:55:57 -07003069 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003070 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003071 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3072 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003073 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003074 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3075 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003076 // Special case to increment nesting level for zero-length maps
3077 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003078 DecodeNesting_Descend(&(pMe->nesting), uType);
3079 }
3080
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003081 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003082
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003083 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3084 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003085
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003086Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003087 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003088}
3089
Laurence Lundblade02625d42020-06-25 14:41:41 -07003090
3091/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003092 This is the common work for exiting a level that is a bounded map,
3093 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003094
3095 One chunk of work is to set up the pre-order traversal so it is at
3096 the item just after the bounded map, array or bstr that is being
3097 exited. This is somewhat complex.
3098
3099 The other work is to level-up the bounded mode to next higest bounded
3100 mode or the top level if there isn't one.
3101 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003102static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003103ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003104{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003105 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003106
Laurence Lundblade02625d42020-06-25 14:41:41 -07003107 /*
3108 First the pre-order-traversal byte offset is positioned to the
3109 item just after the bounded mode item that was just consumed.
3110 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003111 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3112
Laurence Lundblade02625d42020-06-25 14:41:41 -07003113 /*
3114 Next, set the current nesting level to one above the bounded level
3115 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003116
Laurence Lundblade02625d42020-06-25 14:41:41 -07003117 DecodeNesting_CheckBoundedType() is always called before this and
3118 makes sure pCurrentBounded is valid.
3119 */
3120 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3121
3122 /*
3123 This does the complex work of leveling up the pre-order traversal
3124 when the end of a map or array or another bounded level is
3125 reached. It may do nothing, or ascend all the way to the top
3126 level.
3127 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003128 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003129 if(uErr != QCBOR_SUCCESS) {
3130 goto Done;
3131 }
3132
Laurence Lundblade02625d42020-06-25 14:41:41 -07003133 /*
3134 This makes the next highest bounded level the current bounded
3135 level. If there is no next highest level, then no bounded mode is
3136 in effect.
3137 */
3138 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003139
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003140 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003141
3142Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003143 return uErr;
3144}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003145
Laurence Lundblade02625d42020-06-25 14:41:41 -07003146
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003147// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003148void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003149{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003150 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003151 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003152 return;
3153 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003154
Laurence Lundblade02625d42020-06-25 14:41:41 -07003155 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003156
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003157 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003158 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003159 goto Done;
3160 }
3161
Laurence Lundblade02625d42020-06-25 14:41:41 -07003162 /*
3163 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003164 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003165 from previous map search, then do a dummy search.
3166 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003167 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003168 QCBORItem Dummy;
3169 Dummy.uLabelType = QCBOR_TYPE_NONE;
3170 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3171 if(uErr != QCBOR_SUCCESS) {
3172 goto Done;
3173 }
3174 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003175
Laurence Lundblade02625d42020-06-25 14:41:41 -07003176 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003177
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003178Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003179 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003180}
3181
3182
Laurence Lundblade1341c592020-04-11 14:19:05 -07003183
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003184static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003185 const QCBORItem *pItem,
3186 uint8_t uTagRequirement,
3187 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003188{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003189 if(pBstr) {
3190 *pBstr = NULLUsefulBufC;
3191 }
3192
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003193 if(pMe->uLastError != QCBOR_SUCCESS) {
3194 // Already in error state; do nothing.
3195 return pMe->uLastError;
3196 }
3197
3198 QCBORError uError = QCBOR_SUCCESS;
3199
3200 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3201 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3202 goto Done;;
3203 }
3204
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003205 const TagSpecification TagSpec =
3206 {
3207 uTagRequirement,
3208 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3209 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3210 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003211
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003212 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003213 if(uError != QCBOR_SUCCESS) {
3214 goto Done;
3215 }
3216
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003217 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003218 // Reverse the decrement done by GetNext() for the bstr so the
3219 // increment in NestLevelAscender() called by ExitBoundedLevel()
3220 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003221 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003222 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003223
3224 if(pBstr) {
3225 *pBstr = pItem->val.string;
3226 }
3227
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003228 // This saves the current length of the UsefulInputBuf and then
3229 // narrows the UsefulInputBuf to start and length of the wrapped
3230 // CBOR that is being entered.
3231 //
3232 // This makes sure the length is less than
3233 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3234 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3235 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3236 // the casts safe. uEndOfBstr will always be less than
3237 // uPreviousLength because of the way UsefulInputBuf works so there
3238 // is no need to check it. There is also a range check in the
3239 // seek.
3240 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003241 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003242 // amount to much code.
3243 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3244 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003245 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003246 goto Done;
3247 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003248 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003249 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003250 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003251
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003253 (uint32_t)uPreviousLength,
3254 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003255Done:
3256 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003257}
3258
3259
Laurence Lundblade02625d42020-06-25 14:41:41 -07003260/*
3261 Public function, see header qcbor/qcbor_decode.h file
3262 */
3263void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003264 uint8_t uTagRequirement,
3265 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003266{
3267 if(pMe->uLastError != QCBOR_SUCCESS) {
3268 // Already in error state; do nothing.
3269 return;
3270 }
3271
3272 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003273 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003274 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3275 if(pMe->uLastError != QCBOR_SUCCESS) {
3276 return;
3277 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003278
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003279 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003280 &Item,
3281 uTagRequirement,
3282 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003283}
3284
3285
Laurence Lundblade02625d42020-06-25 14:41:41 -07003286/*
3287 Public function, see header qcbor/qcbor_decode.h file
3288 */
3289void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003290 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003291 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003292 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003293{
3294 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003295 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003296
Laurence Lundblade93d89472020-10-03 22:30:50 -07003297 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3298 &Item,
3299 uTagRequirement,
3300 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003301}
3302
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003303
Laurence Lundblade02625d42020-06-25 14:41:41 -07003304/*
3305 Public function, see header qcbor/qcbor_decode.h file
3306 */
3307void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003308 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003309 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003310 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003311{
3312 QCBORItem Item;
3313 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3314
Laurence Lundblade93d89472020-10-03 22:30:50 -07003315 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3316 &Item,
3317 uTagRequirement,
3318 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003319}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003320
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003321
Laurence Lundblade02625d42020-06-25 14:41:41 -07003322/*
3323 Public function, see header qcbor/qcbor_decode.h file
3324 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003325void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003326{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003327 if(pMe->uLastError != QCBOR_SUCCESS) {
3328 // Already in error state; do nothing.
3329 return;
3330 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003331
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003332 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003333 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003334 return;
3335 }
3336
3337 /*
3338 Reset the length of the UsefulInputBuf to what it was before
3339 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003340 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003341 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003342 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003343
3344
Laurence Lundblade02625d42020-06-25 14:41:41 -07003345 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003346 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003347}
3348
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003349
Laurence Lundbladee6430642020-03-14 21:15:44 -07003350
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003351
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003352
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003353
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003354
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003355
Laurence Lundblade93d89472020-10-03 22:30:50 -07003356static QCBORError
3357InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003358{
3359 switch(pItem->uDataType) {
3360 case QCBOR_TYPE_TRUE:
3361 *pBool = true;
3362 return QCBOR_SUCCESS;
3363 break;
3364
3365 case QCBOR_TYPE_FALSE:
3366 *pBool = false;
3367 return QCBOR_SUCCESS;
3368 break;
3369
3370 default:
3371 return QCBOR_ERR_UNEXPECTED_TYPE;
3372 break;
3373 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003374 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003375}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003376
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003377
Laurence Lundblade9b334962020-08-27 10:55:53 -07003378
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003379/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003380 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003381*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003382void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003383{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003384 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003385 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386 return;
3387 }
3388
Laurence Lundbladec4537442020-04-14 18:53:22 -07003389 QCBORError nError;
3390 QCBORItem Item;
3391
3392 nError = QCBORDecode_GetNext(pMe, &Item);
3393 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003394 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003395 return;
3396 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003397 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003398}
3399
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003400
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003401/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003402 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003403*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003404void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003405{
3406 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003407 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408
Laurence Lundblade9b334962020-08-27 10:55:53 -07003409 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003410}
3411
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003412
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003413/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003414 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003415*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003416void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3417{
3418 QCBORItem Item;
3419 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3420
Laurence Lundblade9b334962020-08-27 10:55:53 -07003421 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003422}
3423
3424
3425
Laurence Lundbladec7114722020-08-13 05:11:40 -07003426
3427static void ProcessEpochDate(QCBORDecodeContext *pMe,
3428 QCBORItem *pItem,
3429 uint8_t uTagRequirement,
3430 int64_t *pnTime)
3431{
3432 if(pMe->uLastError != QCBOR_SUCCESS) {
3433 // Already in error state, do nothing
3434 return;
3435 }
3436
3437 QCBORError uErr;
3438
3439 const TagSpecification TagSpec =
3440 {
3441 uTagRequirement,
3442 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3443 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3444 };
3445
Laurence Lundblade4b270642020-08-14 12:53:07 -07003446 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003447 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3448 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003449 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003450 if(uErr != QCBOR_SUCCESS) {
3451 goto Done;
3452 }
3453
3454 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3455 uErr = DecodeDateEpoch(pItem);
3456 if(uErr != QCBOR_SUCCESS) {
3457 goto Done;
3458 }
3459 }
3460
Laurence Lundblade9b334962020-08-27 10:55:53 -07003461 // Save the tags in the last item's tags in the decode context
3462 // for QCBORDecode_GetNthTagOfLast()
3463 CopyTags(pMe, pItem);
3464
Laurence Lundbladec7114722020-08-13 05:11:40 -07003465 *pnTime = pItem->val.epochDate.nSeconds;
3466
3467Done:
3468 pMe->uLastError = (uint8_t)uErr;
3469}
3470
3471
3472void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3473 uint8_t uTagRequirement,
3474 int64_t *pnTime)
3475{
3476 if(pMe->uLastError != QCBOR_SUCCESS) {
3477 // Already in error state, do nothing
3478 return;
3479 }
3480
3481 QCBORItem Item;
3482 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3483
3484 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3485}
3486
3487
3488void
3489QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3490 int64_t nLabel,
3491 uint8_t uTagRequirement,
3492 int64_t *pnTime)
3493{
3494 QCBORItem Item;
3495 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3496 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3497}
3498
3499
3500void
3501QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3502 const char *szLabel,
3503 uint8_t uTagRequirement,
3504 int64_t *pnTime)
3505{
3506 QCBORItem Item;
3507 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3508 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3509}
3510
3511
3512
3513
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003514void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3515 TagSpecification TagSpec,
3516 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003517{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003518 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003519 // Already in error state, do nothing
3520 return;
3521 }
3522
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003523 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003524 QCBORItem Item;
3525
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003526 uError = QCBORDecode_GetNext(pMe, &Item);
3527 if(uError != QCBOR_SUCCESS) {
3528 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003529 return;
3530 }
3531
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003532 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003533
3534 if(pMe->uLastError == QCBOR_SUCCESS) {
3535 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003536 } else {
3537 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003538 }
3539}
3540
Laurence Lundbladec4537442020-04-14 18:53:22 -07003541
3542
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003543
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003544static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003545 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003546 UsefulBufC *pValue,
3547 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003548{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003549 const TagSpecification TagSpec =
3550 {
3551 uTagRequirement,
3552 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3553 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3554 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003555
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003556 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003557 if(uErr != QCBOR_SUCCESS) {
3558 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003559 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003560
3561 *pValue = pItem->val.string;
3562
3563 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3564 *pbIsNegative = false;
3565 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3566 *pbIsNegative = true;
3567 }
3568
3569 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003570}
3571
3572
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003573/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003574 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003575 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003576void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3577 uint8_t uTagRequirement,
3578 UsefulBufC *pValue,
3579 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003580{
3581 if(pMe->uLastError != QCBOR_SUCCESS) {
3582 // Already in error state, do nothing
3583 return;
3584 }
3585
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003586 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003587 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3588 if(uError != QCBOR_SUCCESS) {
3589 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003590 return;
3591 }
3592
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003593 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003594}
3595
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003596
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003597/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003598 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003599*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003600void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3601 int64_t nLabel,
3602 uint8_t uTagRequirement,
3603 UsefulBufC *pValue,
3604 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003605{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003606 QCBORItem Item;
3607 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003608 if(pMe->uLastError != QCBOR_SUCCESS) {
3609 return;
3610 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003611
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003612 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003613}
3614
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003615
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003616/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003617 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003618*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003619void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3620 const char *szLabel,
3621 uint8_t uTagRequirement,
3622 UsefulBufC *pValue,
3623 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003624{
3625 QCBORItem Item;
3626 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003627 if(pMe->uLastError != QCBOR_SUCCESS) {
3628 return;
3629 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003630
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003631 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003632}
3633
3634
3635
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003636
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003637// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003638QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3639 const QCBORItem *pItem,
3640 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003641 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003642{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003643 const TagSpecification TagSpecText =
3644 {
3645 uTagRequirement,
3646 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3647 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3648 };
3649 const TagSpecification TagSpecBinary =
3650 {
3651 uTagRequirement,
3652 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3653 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3654 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003655
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003657
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003658 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003659 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003660 if(pbIsTag257 != NULL) {
3661 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003662 }
3663 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003664 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003665 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003666 if(pbIsTag257 != NULL) {
3667 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668 }
3669 uReturn = QCBOR_SUCCESS;
3670
3671 } else {
3672 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3673 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003674
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003675 return uReturn;
3676}
3677
Laurence Lundblade93d89472020-10-03 22:30:50 -07003678// Improvement: add methods for wrapped CBOR, a simple alternate
3679// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003680
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003681
3682
3683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003684#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003685
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003686typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003687
3688
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003689// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003690static QCBORError
3691Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003692{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003693 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003694
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003695 if(uResult != 0) {
3696 /* This loop will run a maximum of 19 times because
3697 * UINT64_MAX < 10 ^^ 19. More than that will cause
3698 * exit with the overflow error
3699 */
3700 for(; nExponent > 0; nExponent--) {
3701 if(uResult > UINT64_MAX / 10) {
3702 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3703 }
3704 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003705 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003706
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003707 for(; nExponent < 0; nExponent++) {
3708 uResult = uResult / 10;
3709 if(uResult == 0) {
3710 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3711 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003713 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003714 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003715
3716 *puResult = uResult;
3717
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003718 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003719}
3720
3721
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003722// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003723static QCBORError
3724Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003725{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003726 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003728 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003729
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003730 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003732 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003733 */
3734 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003735 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003736 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003738 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739 nExponent--;
3740 }
3741
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003742 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003743 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003744 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3745 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003746 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003747 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003748 }
3749
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003750 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003751
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003752 return QCBOR_SUCCESS;
3753}
3754
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003755
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003756/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003757 Compute value with signed mantissa and signed result. Works with
3758 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003759 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003760static inline QCBORError ExponentiateNN(int64_t nMantissa,
3761 int64_t nExponent,
3762 int64_t *pnResult,
3763 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003764{
3765 uint64_t uResult;
3766
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003767 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003768 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003769 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3770
3771 // Do the exponentiation of the positive mantissa
3772 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3773 if(uReturn) {
3774 return uReturn;
3775 }
3776
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003777
Laurence Lundblade983500d2020-05-14 11:49:34 -07003778 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3779 of INT64_MIN. This assumes two's compliment representation where
3780 INT64_MIN is one increment farther from 0 than INT64_MAX.
3781 Trying to write -INT64_MIN doesn't work to get this because the
3782 compiler tries to work with an int64_t which can't represent
3783 -INT64_MIN.
3784 */
3785 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3786
3787 // Error out if too large
3788 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003789 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3790 }
3791
3792 // Casts are safe because of checks above
3793 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3794
3795 return QCBOR_SUCCESS;
3796}
3797
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003798
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003800 Compute value with signed mantissa and unsigned result. Works with
3801 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003802 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003803static inline QCBORError ExponentitateNU(int64_t nMantissa,
3804 int64_t nExponent,
3805 uint64_t *puResult,
3806 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003807{
3808 if(nMantissa < 0) {
3809 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3810 }
3811
3812 // Cast to unsigned is OK because of check for negative
3813 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3814 // Exponentiation is straight forward
3815 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3816}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003817
3818
3819/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003820 Compute value with signed mantissa and unsigned result. Works with
3821 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003822 */
3823static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3824 int64_t nExponent,
3825 uint64_t *puResult,
3826 fExponentiator pfExp)
3827{
3828 return (*pfExp)(uMantissa, nExponent, puResult);
3829}
3830
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003831#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3832
3833
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003834
3835
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003836
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003837static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003842 const uint8_t *pByte = BigNum.ptr;
3843 size_t uLen = BigNum.len;
3844 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003845 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003846 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003848 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003849 }
3850
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851 *pResult = uResult;
3852 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003853}
3854
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003855
Laurence Lundblade887add82020-05-17 05:50:34 -07003856static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003858 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003859}
3860
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003861
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003862static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003863{
3864 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003865 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3866 if(uError) {
3867 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003868 }
3869 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3870 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003871 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003872}
3873
3874
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003875static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003876{
3877 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003878 /* The negative integer furthest from zero for a C int64_t is
3879 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3880 negative number in CBOR is computed as -n - 1 where n is the
3881 encoded integer, where n is what is in the variable BigNum. When
3882 converting BigNum to a uint64_t, the maximum value is thus
3883 INT64_MAX, so that when it -n - 1 is applied to it the result will
3884 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003885
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003886 -n - 1 <= INT64_MIN.
3887 -n - 1 <= -INT64_MAX - 1
3888 n <= INT64_MAX.
3889 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003890 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003891 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003892 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003893 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003894
3895 /// Now apply -n - 1. The cast is safe because
3896 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3897 // is the largest positive integer that an int64_t can
3898 // represent. */
3899 *pnResult = -(int64_t)uResult - 1;
3900
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003901 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003902}
3903
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003904
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003905
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003906
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003907
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003908/*
3909Convert a integers and floats to an int64_t.
3910
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003911\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003912
Laurence Lundblade93d89472020-10-03 22:30:50 -07003913\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3914 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003915
3916\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3917
Laurence Lundblade93d89472020-10-03 22:30:50 -07003918\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3919 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003920*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003921static QCBORError
3922ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003923{
3924 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003925 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003926 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003927#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003928 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003929 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3930 http://www.cplusplus.com/reference/cmath/llround/
3931 */
3932 // Not interested in FE_INEXACT
3933 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003934 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3935 *pnValue = llround(pItem->val.dfnum);
3936 } else {
3937 *pnValue = lroundf(pItem->val.fnum);
3938 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003939 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3940 // llround() shouldn't result in divide by zero, but catch
3941 // it here in case it unexpectedly does. Don't try to
3942 // distinguish between the various exceptions because it seems
3943 // they vary by CPU, compiler and OS.
3944 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003945 }
3946 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003947 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003948 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003949#else
3950 return QCBOR_ERR_HW_FLOAT_DISABLED;
3951#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003952 break;
3953
3954 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003956 *pnValue = pItem->val.int64;
3957 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003958 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003959 }
3960 break;
3961
3962 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003963 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003964 if(pItem->val.uint64 < INT64_MAX) {
3965 *pnValue = pItem->val.int64;
3966 } else {
3967 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3968 }
3969 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003970 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003971 }
3972 break;
3973
3974 default:
3975 return QCBOR_ERR_UNEXPECTED_TYPE;
3976 }
3977 return QCBOR_SUCCESS;
3978}
3979
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003980
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003981void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003983 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003984 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003985{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003986 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003987 return;
3988 }
3989
Laurence Lundbladee6430642020-03-14 21:15:44 -07003990 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003991 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3992 if(uError) {
3993 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003994 return;
3995 }
3996
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003997 if(pItem) {
3998 *pItem = Item;
3999 }
4000
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004001 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004002}
4003
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004004
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004005void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4006 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008 int64_t *pnValue,
4009 QCBORItem *pItem)
4010{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004011 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004012 if(pMe->uLastError != QCBOR_SUCCESS) {
4013 return;
4014 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004016 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004017}
4018
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004019
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004020void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4021 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 int64_t *pnValue,
4024 QCBORItem *pItem)
4025{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004026 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004027 if(pMe->uLastError != QCBOR_SUCCESS) {
4028 return;
4029 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004031 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004032}
4033
4034
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004035/*
4036 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004037
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004039
Laurence Lundblade93d89472020-10-03 22:30:50 -07004040 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4041 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004042
4043 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4044
Laurence Lundblade93d89472020-10-03 22:30:50 -07004045 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4046 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004047 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004048static QCBORError
4049Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004050{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051 switch(pItem->uDataType) {
4052
4053 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004058 }
4059 break;
4060
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004061 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004064 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004066 }
4067 break;
4068
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4070 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004073 pItem->val.expAndMantissa.nExponent,
4074 pnValue,
4075 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004076 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004077 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078 }
4079 break;
4080
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004081 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004082 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004083 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004084 pItem->val.expAndMantissa.nExponent,
4085 pnValue,
4086 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004088 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004089 }
4090 break;
4091
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004092 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004093 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004094 int64_t nMantissa;
4095 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4097 if(uErr) {
4098 return uErr;
4099 }
4100 return ExponentiateNN(nMantissa,
4101 pItem->val.expAndMantissa.nExponent,
4102 pnValue,
4103 Exponentitate10);
4104 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106 }
4107 break;
4108
4109 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004110 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004111 int64_t nMantissa;
4112 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004113 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4114 if(uErr) {
4115 return uErr;
4116 }
4117 return ExponentiateNN(nMantissa,
4118 pItem->val.expAndMantissa.nExponent,
4119 pnValue,
4120 Exponentitate10);
4121 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123 }
4124 break;
4125
4126 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004128 int64_t nMantissa;
4129 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004130 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4131 if(uErr) {
4132 return uErr;
4133 }
4134 return ExponentiateNN(nMantissa,
4135 pItem->val.expAndMantissa.nExponent,
4136 pnValue,
4137 Exponentitate2);
4138 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004139 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140 }
4141 break;
4142
4143 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004145 int64_t nMantissa;
4146 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004147 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4148 if(uErr) {
4149 return uErr;
4150 }
4151 return ExponentiateNN(nMantissa,
4152 pItem->val.expAndMantissa.nExponent,
4153 pnValue,
4154 Exponentitate2);
4155 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004156 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004157 }
4158 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004159#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4160
Laurence Lundbladee6430642020-03-14 21:15:44 -07004161
Laurence Lundbladec4537442020-04-14 18:53:22 -07004162 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004163 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004164}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004165
4166
Laurence Lundbladec4537442020-04-14 18:53:22 -07004167/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004168 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004169 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004171{
4172 QCBORItem Item;
4173
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004174 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004175
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004176 if(pMe->uLastError == QCBOR_SUCCESS) {
4177 // The above conversion succeeded
4178 return;
4179 }
4180
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004181 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004182 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004183 return;
4184 }
4185
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004186 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004187}
4188
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004189
4190/*
4191Public function, see header qcbor/qcbor_decode.h file
4192*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004193void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4194 int64_t nLabel,
4195 uint32_t uConvertTypes,
4196 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004197{
4198 QCBORItem Item;
4199
Laurence Lundblade93d89472020-10-03 22:30:50 -07004200 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4201 nLabel,
4202 uConvertTypes,
4203 pnValue,
4204 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205
4206 if(pMe->uLastError == QCBOR_SUCCESS) {
4207 // The above conversion succeeded
4208 return;
4209 }
4210
4211 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4212 // The above conversion failed in a way that code below can't correct
4213 return;
4214 }
4215
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004217}
4218
4219
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004220/*
4221Public function, see header qcbor/qcbor_decode.h file
4222*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004223void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4224 const char *szLabel,
4225 uint32_t uConvertTypes,
4226 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004227{
4228 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004229 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4230 szLabel,
4231 uConvertTypes,
4232 pnValue,
4233 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234
4235 if(pMe->uLastError == QCBOR_SUCCESS) {
4236 // The above conversion succeeded
4237 return;
4238 }
4239
4240 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4241 // The above conversion failed in a way that code below can't correct
4242 return;
4243 }
4244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246}
4247
4248
Laurence Lundblade93d89472020-10-03 22:30:50 -07004249static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004250{
4251 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004252 case QCBOR_TYPE_DOUBLE:
4253 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004254#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004255 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004256 // Can't use llround here because it will not convert values
4257 // greater than INT64_MAX and less than UINT64_MAX that
4258 // need to be converted so it is more complicated.
4259 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4260 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4261 if(isnan(pItem->val.dfnum)) {
4262 return QCBOR_ERR_FLOAT_EXCEPTION;
4263 } else if(pItem->val.dfnum < 0) {
4264 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4265 } else {
4266 double dRounded = round(pItem->val.dfnum);
4267 // See discussion in DecodeDateEpoch() for
4268 // explanation of - 0x7ff
4269 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4270 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4271 }
4272 *puValue = (uint64_t)dRounded;
4273 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004274 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004275 if(isnan(pItem->val.fnum)) {
4276 return QCBOR_ERR_FLOAT_EXCEPTION;
4277 } else if(pItem->val.fnum < 0) {
4278 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4279 } else {
4280 float fRounded = roundf(pItem->val.fnum);
4281 // See discussion in DecodeDateEpoch() for
4282 // explanation of - 0x7ff
4283 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4284 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4285 }
4286 *puValue = (uint64_t)fRounded;
4287 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004288 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004289 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4290 // round() and roundf() shouldn't result in exceptions here, but
4291 // catch them to be robust and thorough. Don't try to
4292 // distinguish between the various exceptions because it seems
4293 // they vary by CPU, compiler and OS.
4294 return QCBOR_ERR_FLOAT_EXCEPTION;
4295 }
4296
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004297 } else {
4298 return QCBOR_ERR_UNEXPECTED_TYPE;
4299 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004300#else
4301 return QCBOR_ERR_HW_FLOAT_DISABLED;
4302#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004305 case QCBOR_TYPE_INT64:
4306 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4307 if(pItem->val.int64 >= 0) {
4308 *puValue = (uint64_t)pItem->val.int64;
4309 } else {
4310 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4311 }
4312 } else {
4313 return QCBOR_ERR_UNEXPECTED_TYPE;
4314 }
4315 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004316
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004317 case QCBOR_TYPE_UINT64:
4318 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4319 *puValue = pItem->val.uint64;
4320 } else {
4321 return QCBOR_ERR_UNEXPECTED_TYPE;
4322 }
4323 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004324
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004325 default:
4326 return QCBOR_ERR_UNEXPECTED_TYPE;
4327 }
4328
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004329 return QCBOR_SUCCESS;
4330}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004331
4332
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004333void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004336 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004337{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004338 if(pMe->uLastError != QCBOR_SUCCESS) {
4339 return;
4340 }
4341
Laurence Lundbladec4537442020-04-14 18:53:22 -07004342 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004344 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4345 if(uError) {
4346 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004347 return;
4348 }
4349
Laurence Lundbladea826c502020-05-10 21:07:00 -07004350 if(pItem) {
4351 *pItem = Item;
4352 }
4353
Laurence Lundblade93d89472020-10-03 22:30:50 -07004354 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004355}
4356
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004357
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004358void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004359 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004360 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004361 uint64_t *puValue,
4362 QCBORItem *pItem)
4363{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004364 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004365 if(pMe->uLastError != QCBOR_SUCCESS) {
4366 return;
4367 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004368
Laurence Lundblade93d89472020-10-03 22:30:50 -07004369 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370}
4371
4372
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004373void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004374 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004375 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376 uint64_t *puValue,
4377 QCBORItem *pItem)
4378{
4379 if(pMe->uLastError != QCBOR_SUCCESS) {
4380 return;
4381 }
4382
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004383 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004384 if(pMe->uLastError != QCBOR_SUCCESS) {
4385 return;
4386 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387
Laurence Lundblade93d89472020-10-03 22:30:50 -07004388 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389}
4390
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004391
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004392/*
4393 Public function, see header qcbor/qcbor_decode.h file
4394*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004395static QCBORError
4396UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004397{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004398 switch(pItem->uDataType) {
4399
4400 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004401 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4403 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004404 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405 }
4406 break;
4407
4408 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004409 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004410 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4411 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004412 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413 }
4414 break;
4415
4416#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4417
4418 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004419 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004420 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004421 pItem->val.expAndMantissa.nExponent,
4422 puValue,
4423 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426 }
4427 break;
4428
4429 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004430 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004431 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4432 pItem->val.expAndMantissa.nExponent,
4433 puValue,
4434 Exponentitate2);
4435 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437 }
4438 break;
4439
4440 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004441 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004442 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004443 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004444 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445 if(uErr != QCBOR_SUCCESS) {
4446 return uErr;
4447 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004448 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 pItem->val.expAndMantissa.nExponent,
4450 puValue,
4451 Exponentitate10);
4452 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004453 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454 }
4455 break;
4456
4457 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004458 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4460 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 }
4463 break;
4464
4465 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004467 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004468 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004469 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004470 if(uErr != QCBOR_SUCCESS) {
4471 return uErr;
4472 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004473 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 pItem->val.expAndMantissa.nExponent,
4475 puValue,
4476 Exponentitate2);
4477 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 }
4480 break;
4481
4482 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4485 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004486 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487 }
4488 break;
4489#endif
4490 default:
4491 return QCBOR_ERR_UNEXPECTED_TYPE;
4492 }
4493}
4494
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004495
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004496/*
4497 Public function, see header qcbor/qcbor_decode.h file
4498*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004500{
4501 QCBORItem Item;
4502
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004504
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004505 if(pMe->uLastError == QCBOR_SUCCESS) {
4506 // The above conversion succeeded
4507 return;
4508 }
4509
4510 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4511 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004512 return;
4513 }
4514
Laurence Lundblade93d89472020-10-03 22:30:50 -07004515 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004516}
4517
Laurence Lundbladec4537442020-04-14 18:53:22 -07004518
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004519/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004520 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004522void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004523 int64_t nLabel,
4524 uint32_t uConvertTypes,
4525 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526{
4527 QCBORItem Item;
4528
Laurence Lundblade93d89472020-10-03 22:30:50 -07004529 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4530 nLabel,
4531 uConvertTypes,
4532 puValue,
4533 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534
4535 if(pMe->uLastError == QCBOR_SUCCESS) {
4536 // The above conversion succeeded
4537 return;
4538 }
4539
4540 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4541 // The above conversion failed in a way that code below can't correct
4542 return;
4543 }
4544
Laurence Lundblade93d89472020-10-03 22:30:50 -07004545 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546}
4547
4548
4549/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004550 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004551*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004552void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004553 const char *szLabel,
4554 uint32_t uConvertTypes,
4555 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556{
4557 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004558 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4559 szLabel,
4560 uConvertTypes,
4561 puValue,
4562 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004563
4564 if(pMe->uLastError == QCBOR_SUCCESS) {
4565 // The above conversion succeeded
4566 return;
4567 }
4568
4569 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4570 // The above conversion failed in a way that code below can't correct
4571 return;
4572 }
4573
Laurence Lundblade93d89472020-10-03 22:30:50 -07004574 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004575}
4576
4577
Laurence Lundblade9b334962020-08-27 10:55:53 -07004578static QCBORError ConvertDouble(const QCBORItem *pItem,
4579 uint32_t uConvertTypes,
4580 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581{
4582 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004583 case QCBOR_TYPE_FLOAT:
4584#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4585 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4586 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004587 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004588 *pdValue = (double)pItem->val.fnum;
4589 } else {
4590 return QCBOR_ERR_UNEXPECTED_TYPE;
4591 }
4592 }
4593#else
4594 return QCBOR_ERR_HW_FLOAT_DISABLED;
4595#endif
4596 break;
4597
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004599 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4600 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601 *pdValue = pItem->val.dfnum;
4602 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004603 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004604 }
4605 }
4606 break;
4607
4608 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004609#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004610 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004611 // A simple cast seems to do the job with no worry of exceptions.
4612 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613 *pdValue = (double)pItem->val.int64;
4614
4615 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004616 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004618#else
4619 return QCBOR_ERR_HW_FLOAT_DISABLED;
4620#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004621 break;
4622
4623 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004624#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004625 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004626 // A simple cast seems to do the job with no worry of exceptions.
4627 // There will be precision loss for some values.
4628 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631 }
4632 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004633#else
4634 return QCBOR_ERR_HW_FLOAT_DISABLED;
4635#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004636
4637 default:
4638 return QCBOR_ERR_UNEXPECTED_TYPE;
4639 }
4640
4641 return QCBOR_SUCCESS;
4642}
4643
4644
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004645void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004646 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004647 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004648 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004649{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004650 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004651 return;
4652 }
4653
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004654 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004655
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004656 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004657 if(uError) {
4658 pMe->uLastError = (uint8_t)uError;
4659 return;
4660 }
4661
4662 if(pItem) {
4663 *pItem = Item;
4664 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004665
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004667}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004668
Laurence Lundbladec4537442020-04-14 18:53:22 -07004669
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4671 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004672 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004673 double *pdValue,
4674 QCBORItem *pItem)
4675{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004676 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004677 if(pMe->uLastError != QCBOR_SUCCESS) {
4678 return;
4679 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004682}
4683
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004684
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4686 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004687 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688 double *pdValue,
4689 QCBORItem *pItem)
4690{
4691 if(pMe->uLastError != QCBOR_SUCCESS) {
4692 return;
4693 }
4694
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004695 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004696 if(pMe->uLastError != QCBOR_SUCCESS) {
4697 return;
4698 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701}
4702
4703
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004704#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004705static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4706{
4707 double dResult;
4708
4709 dResult = 0.0;
4710 const uint8_t *pByte = BigNum.ptr;
4711 size_t uLen = BigNum.len;
4712 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004713 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004714 while(uLen--) {
4715 dResult = (dResult * 256.0) + (double)*pByte++;
4716 }
4717
4718 return dResult;
4719}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004720#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4721
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004722
Laurence Lundblade93d89472020-10-03 22:30:50 -07004723static QCBORError
4724DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004725{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004726#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004727 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004728 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4729
4730 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004731 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004732
4733#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004736 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4738 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4739 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004740 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741 }
4742 break;
4743
4744 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004746 // Underflow gives 0, overflow gives infinity
4747 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4748 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004750 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751 }
4752 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004753#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754
4755 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4758 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004759 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760 }
4761 break;
4762
4763 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004765 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004767 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768 }
4769 break;
4770
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004771#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004773 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4775 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
4779 break;
4780
4781 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4784 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4785 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 }
4788 break;
4789
4790 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4793 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4794 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004795 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004796 }
4797 break;
4798
4799 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004801 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4803 } 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 */
4808
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004809 default:
4810 return QCBOR_ERR_UNEXPECTED_TYPE;
4811 }
4812
4813 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004814
4815#else
4816 (void)pItem;
4817 (void)uConvertTypes;
4818 (void)pdValue;
4819 return QCBOR_ERR_HW_FLOAT_DISABLED;
4820#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4821
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822}
4823
4824
4825/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004826 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004828void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4829 uint32_t uConvertTypes,
4830 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004831{
4832
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004833 QCBORItem Item;
4834
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004836
4837 if(pMe->uLastError == QCBOR_SUCCESS) {
4838 // The above conversion succeeded
4839 return;
4840 }
4841
4842 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4843 // The above conversion failed in a way that code below can't correct
4844 return;
4845 }
4846
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004847 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004848}
4849
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850
4851/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004852 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004854void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4855 int64_t nLabel,
4856 uint32_t uConvertTypes,
4857 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858{
4859 QCBORItem Item;
4860
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004861 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862
4863 if(pMe->uLastError == QCBOR_SUCCESS) {
4864 // The above conversion succeeded
4865 return;
4866 }
4867
4868 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4869 // The above conversion failed in a way that code below can't correct
4870 return;
4871 }
4872
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004873 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004874}
4875
4876
4877/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004878 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004880void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4881 const char *szLabel,
4882 uint32_t uConvertTypes,
4883 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884{
4885 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004886 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004887
4888 if(pMe->uLastError == QCBOR_SUCCESS) {
4889 // The above conversion succeeded
4890 return;
4891 }
4892
4893 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4894 // The above conversion failed in a way that code below can't correct
4895 return;
4896 }
4897
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004898 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004899}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004900
4901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004902
4903
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004904#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004905static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4906{
4907 while((uInt & 0xff00000000000000UL) == 0) {
4908 uInt = uInt << 8;
4909 };
4910
4911 UsefulOutBuf UOB;
4912
4913 UsefulOutBuf_Init(&UOB, Buffer);
4914
4915 while(uInt) {
4916 const uint64_t xx = uInt & 0xff00000000000000UL;
4917 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4918 uInt = uInt << 8;
4919 (void)xx;
4920 }
4921
4922 return UsefulOutBuf_OutUBuf(&UOB);
4923}
4924
4925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004926static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4927 TagSpecification TagSpec,
4928 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004929{
4930 QCBORError uErr;
4931 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004932 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004933 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004934 if(uErr != QCBOR_SUCCESS) {
4935 goto Done;
4936 }
4937
4938 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4939 break; // Successful exit. Moving on to finish decoding.
4940 }
4941
4942 // The item is an array, which means an undecoded
4943 // mantissa and exponent, so decode it. It will then
4944 // have a different type and exit the loop if.
4945 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4946 if(uErr != QCBOR_SUCCESS) {
4947 goto Done;
4948 }
4949
4950 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004951 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004952 }
4953Done:
4954 return uErr;
4955}
4956
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004957
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004958static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004959 TagSpecification TagSpec,
4960 QCBORItem *pItem,
4961 int64_t *pnMantissa,
4962 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004963{
4964 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004965
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004966 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004967 if(uErr != QCBOR_SUCCESS) {
4968 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004969 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004970
Laurence Lundblade9b334962020-08-27 10:55:53 -07004971 switch (pItem->uDataType) {
4972
4973 case QCBOR_TYPE_DECIMAL_FRACTION:
4974 case QCBOR_TYPE_BIGFLOAT:
4975 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4976 *pnExponent = pItem->val.expAndMantissa.nExponent;
4977 break;
4978
4979 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4980 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4981 *pnExponent = pItem->val.expAndMantissa.nExponent;
4982 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4983 break;
4984
4985 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4986 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4987 *pnExponent = pItem->val.expAndMantissa.nExponent;
4988 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4989 break;
4990
4991 default:
4992 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4993 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004994
4995 Done:
4996 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004997}
4998
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004999
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005000static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005001 TagSpecification TagSpec,
5002 QCBORItem *pItem,
5003 UsefulBuf BufferForMantissa,
5004 UsefulBufC *pMantissa,
5005 bool *pbIsNegative,
5006 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005007{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005008 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005009
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005010 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005011 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005012 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005013 }
5014
5015 uint64_t uMantissa;
5016
5017 switch (pItem->uDataType) {
5018
5019 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005020 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005021 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5022 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5023 *pbIsNegative = false;
5024 } else {
5025 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5026 *pbIsNegative = true;
5027 }
5028 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5029 *pnExponent = pItem->val.expAndMantissa.nExponent;
5030 break;
5031
5032 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005034 *pnExponent = pItem->val.expAndMantissa.nExponent;
5035 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5036 *pbIsNegative = false;
5037 break;
5038
5039 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005040 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005041 *pnExponent = pItem->val.expAndMantissa.nExponent;
5042 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5043 *pbIsNegative = true;
5044 break;
5045
5046 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005049
5050Done:
5051 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005052}
5053
5054
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005055/*
5056 Public function, see header qcbor/qcbor_decode.h file
5057*/
5058void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5059 uint8_t uTagRequirement,
5060 int64_t *pnMantissa,
5061 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005062{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063 if(pMe->uLastError != QCBOR_SUCCESS) {
5064 return;
5065 }
5066
5067 QCBORItem Item;
5068 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5069 if(uError) {
5070 pMe->uLastError = (uint8_t)uError;
5071 return;
5072 }
5073
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005074 const TagSpecification TagSpec =
5075 {
5076 uTagRequirement,
5077 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5078 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5079 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005080
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005081 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005082}
5083
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005084
5085/*
5086 Public function, see header qcbor/qcbor_decode.h file
5087*/
5088void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005089 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005090 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005091 int64_t *pnMantissa,
5092 int64_t *pnExponent)
5093{
5094 if(pMe->uLastError != QCBOR_SUCCESS) {
5095 return;
5096 }
5097
5098 QCBORItem Item;
5099 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5100
5101 const TagSpecification TagSpec =
5102 {
5103 uTagRequirement,
5104 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5105 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5106 };
5107
5108 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5109}
5110
5111
5112/*
5113 Public function, see header qcbor/qcbor_decode.h file
5114*/
5115void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005116 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005117 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 int64_t *pnMantissa,
5119 int64_t *pnExponent)
5120{
5121 if(pMe->uLastError != QCBOR_SUCCESS) {
5122 return;
5123 }
5124
5125 QCBORItem Item;
5126 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5127
5128 const TagSpecification TagSpec =
5129 {
5130 uTagRequirement,
5131 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5132 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5133 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005134
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005135 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5136}
5137
5138
5139/*
5140 Public function, see header qcbor/qcbor_decode.h file
5141*/
5142void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5143 uint8_t uTagRequirement,
5144 UsefulBuf MantissaBuffer,
5145 UsefulBufC *pMantissa,
5146 bool *pbMantissaIsNegative,
5147 int64_t *pnExponent)
5148{
5149 if(pMe->uLastError != QCBOR_SUCCESS) {
5150 return;
5151 }
5152
5153 QCBORItem Item;
5154 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5155 if(uError) {
5156 pMe->uLastError = (uint8_t)uError;
5157 return;
5158 }
5159
5160 const TagSpecification TagSpec =
5161 {
5162 uTagRequirement,
5163 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5164 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5165 };
5166
Laurence Lundblade93d89472020-10-03 22:30:50 -07005167 ProcessMantissaAndExponentBig(pMe,
5168 TagSpec,
5169 &Item,
5170 MantissaBuffer,
5171 pMantissa,
5172 pbMantissaIsNegative,
5173 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005174}
5175
5176
5177/*
5178 Public function, see header qcbor/qcbor_decode.h file
5179*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005180void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005181 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005182 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005183 UsefulBuf BufferForMantissa,
5184 UsefulBufC *pMantissa,
5185 bool *pbIsNegative,
5186 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005187{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005188 if(pMe->uLastError != QCBOR_SUCCESS) {
5189 return;
5190 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005191
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005192 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005193 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005194 if(pMe->uLastError != QCBOR_SUCCESS) {
5195 return;
5196 }
5197
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005198 const TagSpecification TagSpec =
5199 {
5200 uTagRequirement,
5201 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5202 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5203 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005204
Laurence Lundblade93d89472020-10-03 22:30:50 -07005205 ProcessMantissaAndExponentBig(pMe,
5206 TagSpec,
5207 &Item,
5208 BufferForMantissa,
5209 pMantissa,
5210 pbIsNegative,
5211 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005212}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005213
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005214
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005215/*
5216 Public function, see header qcbor/qcbor_decode.h file
5217*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005218void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005219 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005220 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005221 UsefulBuf BufferForMantissa,
5222 UsefulBufC *pMantissa,
5223 bool *pbIsNegative,
5224 int64_t *pnExponent)
5225{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005226 if(pMe->uLastError != QCBOR_SUCCESS) {
5227 return;
5228 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005229
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005231 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5232 if(pMe->uLastError != QCBOR_SUCCESS) {
5233 return;
5234 }
5235
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005236 const TagSpecification TagSpec =
5237 {
5238 uTagRequirement,
5239 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5240 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5241 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005242
5243 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5244}
5245
5246
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005247/*
5248 Public function, see header qcbor/qcbor_decode.h file
5249*/
5250void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5251 uint8_t uTagRequirement,
5252 int64_t *pnMantissa,
5253 int64_t *pnExponent)
5254{
5255 if(pMe->uLastError != QCBOR_SUCCESS) {
5256 return;
5257 }
5258
5259 QCBORItem Item;
5260 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5261 if(uError) {
5262 pMe->uLastError = (uint8_t)uError;
5263 return;
5264 }
5265 const TagSpecification TagSpec =
5266 {
5267 uTagRequirement,
5268 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5269 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5270 };
5271
5272 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5273}
5274
5275
5276/*
5277 Public function, see header qcbor/qcbor_decode.h file
5278*/
5279void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005280 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005281 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005282 int64_t *pnMantissa,
5283 int64_t *pnExponent)
5284{
5285 if(pMe->uLastError != QCBOR_SUCCESS) {
5286 return;
5287 }
5288
5289 QCBORItem Item;
5290 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5291 if(pMe->uLastError != QCBOR_SUCCESS) {
5292 return;
5293 }
5294
5295 const TagSpecification TagSpec =
5296 {
5297 uTagRequirement,
5298 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5299 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5300 };
5301
5302 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5303}
5304
5305
5306/*
5307 Public function, see header qcbor/qcbor_decode.h file
5308*/
5309void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005310 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005311 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005312 int64_t *pnMantissa,
5313 int64_t *pnExponent)
5314{
5315 if(pMe->uLastError != QCBOR_SUCCESS) {
5316 return;
5317 }
5318
5319 QCBORItem Item;
5320 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5321 if(pMe->uLastError != QCBOR_SUCCESS) {
5322 return;
5323 }
5324
5325 const TagSpecification TagSpec =
5326 {
5327 uTagRequirement,
5328 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5329 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5330 };
5331
5332 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5333}
5334
5335
5336/*
5337 Public function, see header qcbor/qcbor_decode.h file
5338*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005339void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5340 uint8_t uTagRequirement,
5341 UsefulBuf MantissaBuffer,
5342 UsefulBufC *pMantissa,
5343 bool *pbMantissaIsNegative,
5344 int64_t *pnExponent)
5345{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005346 if(pMe->uLastError != QCBOR_SUCCESS) {
5347 return;
5348 }
5349
5350 QCBORItem Item;
5351 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5352 if(uError) {
5353 pMe->uLastError = (uint8_t)uError;
5354 return;
5355 }
5356
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005357 const TagSpecification TagSpec =
5358 {
5359 uTagRequirement,
5360 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5361 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5362 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005363
5364 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005365}
5366
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005367
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005368/*
5369 Public function, see header qcbor/qcbor_decode.h file
5370*/
5371void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005373 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005374 UsefulBuf BufferForMantissa,
5375 UsefulBufC *pMantissa,
5376 bool *pbIsNegative,
5377 int64_t *pnExponent)
5378{
5379 if(pMe->uLastError != QCBOR_SUCCESS) {
5380 return;
5381 }
5382
5383 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005384 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5385 if(pMe->uLastError != QCBOR_SUCCESS) {
5386 return;
5387 }
5388
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005389 const TagSpecification TagSpec =
5390 {
5391 uTagRequirement,
5392 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5393 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5394 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005395
Laurence Lundblade93d89472020-10-03 22:30:50 -07005396 ProcessMantissaAndExponentBig(pMe,
5397 TagSpec,
5398 &Item,
5399 BufferForMantissa,
5400 pMantissa,
5401 pbIsNegative,
5402 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005403}
5404
5405
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005406/*
5407 Public function, see header qcbor/qcbor_decode.h file
5408*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005409void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005411 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005412 UsefulBuf BufferForMantissa,
5413 UsefulBufC *pMantissa,
5414 bool *pbIsNegative,
5415 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005416{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005417 if(pMe->uLastError != QCBOR_SUCCESS) {
5418 return;
5419 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005420
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005421 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005422 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5423 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005424 return;
5425 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005426
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005427 const TagSpecification TagSpec =
5428 {
5429 uTagRequirement,
5430 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5431 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5432 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005433
Laurence Lundblade93d89472020-10-03 22:30:50 -07005434 ProcessMantissaAndExponentBig(pMe,
5435 TagSpec,
5436 &Item,
5437 BufferForMantissa,
5438 pMantissa,
5439 pbIsNegative,
5440 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005441}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005442
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005443#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */