blob: f536f9036d0125cfcd7ad7dc788e0357298bb429 [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 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100937 int nMajorType = 0;
938 uint64_t uNumber = 0;
939 int nAdditionalInfo = 0;
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,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003442 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3443 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003444 };
3445
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003446 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003447 if(uErr != QCBOR_SUCCESS) {
3448 goto Done;
3449 }
3450
3451 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3452 uErr = DecodeDateEpoch(pItem);
3453 if(uErr != QCBOR_SUCCESS) {
3454 goto Done;
3455 }
3456 }
3457
Laurence Lundblade9b334962020-08-27 10:55:53 -07003458 // Save the tags in the last item's tags in the decode context
3459 // for QCBORDecode_GetNthTagOfLast()
3460 CopyTags(pMe, pItem);
3461
Laurence Lundbladec7114722020-08-13 05:11:40 -07003462 *pnTime = pItem->val.epochDate.nSeconds;
3463
3464Done:
3465 pMe->uLastError = (uint8_t)uErr;
3466}
3467
3468
3469void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3470 uint8_t uTagRequirement,
3471 int64_t *pnTime)
3472{
3473 if(pMe->uLastError != QCBOR_SUCCESS) {
3474 // Already in error state, do nothing
3475 return;
3476 }
3477
3478 QCBORItem Item;
3479 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3480
3481 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3482}
3483
3484
3485void
3486QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3487 int64_t nLabel,
3488 uint8_t uTagRequirement,
3489 int64_t *pnTime)
3490{
3491 QCBORItem Item;
3492 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3493 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3494}
3495
3496
3497void
3498QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3499 const char *szLabel,
3500 uint8_t uTagRequirement,
3501 int64_t *pnTime)
3502{
3503 QCBORItem Item;
3504 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3505 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3506}
3507
3508
3509
3510
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003511void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3512 TagSpecification TagSpec,
3513 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003514{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003515 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003516 // Already in error state, do nothing
3517 return;
3518 }
3519
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003520 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003521 QCBORItem Item;
3522
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003523 uError = QCBORDecode_GetNext(pMe, &Item);
3524 if(uError != QCBOR_SUCCESS) {
3525 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003526 return;
3527 }
3528
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003529 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003530
3531 if(pMe->uLastError == QCBOR_SUCCESS) {
3532 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003533 } else {
3534 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003535 }
3536}
3537
Laurence Lundbladec4537442020-04-14 18:53:22 -07003538
3539
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003540
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003541static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003542 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003543 UsefulBufC *pValue,
3544 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003545{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003546 const TagSpecification TagSpec =
3547 {
3548 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003549 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3550 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003551 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003552
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003553 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003554 if(uErr != QCBOR_SUCCESS) {
3555 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003556 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003557
3558 *pValue = pItem->val.string;
3559
3560 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3561 *pbIsNegative = false;
3562 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3563 *pbIsNegative = true;
3564 }
3565
3566 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003567}
3568
3569
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003570/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003571 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003572 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003573void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3574 uint8_t uTagRequirement,
3575 UsefulBufC *pValue,
3576 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003577{
3578 if(pMe->uLastError != QCBOR_SUCCESS) {
3579 // Already in error state, do nothing
3580 return;
3581 }
3582
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003583 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003584 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3585 if(uError != QCBOR_SUCCESS) {
3586 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003587 return;
3588 }
3589
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003590 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003591}
3592
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003593
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003594/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003595 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003596*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003597void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3598 int64_t nLabel,
3599 uint8_t uTagRequirement,
3600 UsefulBufC *pValue,
3601 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003602{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603 QCBORItem Item;
3604 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003605 if(pMe->uLastError != QCBOR_SUCCESS) {
3606 return;
3607 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003608
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003609 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003610}
3611
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003612
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003613/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003614 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003615*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003616void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3617 const char *szLabel,
3618 uint8_t uTagRequirement,
3619 UsefulBufC *pValue,
3620 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003621{
3622 QCBORItem Item;
3623 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003624 if(pMe->uLastError != QCBOR_SUCCESS) {
3625 return;
3626 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003627
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003628 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003629}
3630
3631
3632
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003633
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003634// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003635QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3636 const QCBORItem *pItem,
3637 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003638 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003639{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003640 const TagSpecification TagSpecText =
3641 {
3642 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003643 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3644 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003645 };
3646 const TagSpecification TagSpecBinary =
3647 {
3648 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003649 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3650 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003651 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003652
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003653 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003654
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003655 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003657 if(pbIsTag257 != NULL) {
3658 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003659 }
3660 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003661 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003662 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003663 if(pbIsTag257 != NULL) {
3664 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003665 }
3666 uReturn = QCBOR_SUCCESS;
3667
3668 } else {
3669 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3670 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003671
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003672 return uReturn;
3673}
3674
Laurence Lundblade93d89472020-10-03 22:30:50 -07003675// Improvement: add methods for wrapped CBOR, a simple alternate
3676// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003677
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003678
3679
3680
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003681#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003682
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003683typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003684
3685
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003686// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003687static QCBORError
3688Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003689{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003690 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003691
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003692 if(uResult != 0) {
3693 /* This loop will run a maximum of 19 times because
3694 * UINT64_MAX < 10 ^^ 19. More than that will cause
3695 * exit with the overflow error
3696 */
3697 for(; nExponent > 0; nExponent--) {
3698 if(uResult > UINT64_MAX / 10) {
3699 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3700 }
3701 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003702 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003704 for(; nExponent < 0; nExponent++) {
3705 uResult = uResult / 10;
3706 if(uResult == 0) {
3707 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3708 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003709 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003710 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003711 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712
3713 *puResult = uResult;
3714
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003715 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003716}
3717
3718
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003719// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003720static QCBORError
3721Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003722{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003723 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003724
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003725 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003726
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003727 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003728 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003729 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003730 */
3731 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003732 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003733 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003734 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003735 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003736 nExponent--;
3737 }
3738
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003739 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003740 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003741 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3742 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003743 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003744 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003745 }
3746
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003747 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003748
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003749 return QCBOR_SUCCESS;
3750}
3751
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003752
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003753/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003754 Compute value with signed mantissa and signed result. Works with
3755 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003756 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003757static inline QCBORError ExponentiateNN(int64_t nMantissa,
3758 int64_t nExponent,
3759 int64_t *pnResult,
3760 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003761{
3762 uint64_t uResult;
3763
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003764 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003765 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003766 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3767
3768 // Do the exponentiation of the positive mantissa
3769 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3770 if(uReturn) {
3771 return uReturn;
3772 }
3773
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003774
Laurence Lundblade983500d2020-05-14 11:49:34 -07003775 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3776 of INT64_MIN. This assumes two's compliment representation where
3777 INT64_MIN is one increment farther from 0 than INT64_MAX.
3778 Trying to write -INT64_MIN doesn't work to get this because the
3779 compiler tries to work with an int64_t which can't represent
3780 -INT64_MIN.
3781 */
3782 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3783
3784 // Error out if too large
3785 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003786 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3787 }
3788
3789 // Casts are safe because of checks above
3790 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3791
3792 return QCBOR_SUCCESS;
3793}
3794
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003795
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003796/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003797 Compute value with signed mantissa and unsigned result. Works with
3798 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003800static inline QCBORError ExponentitateNU(int64_t nMantissa,
3801 int64_t nExponent,
3802 uint64_t *puResult,
3803 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804{
3805 if(nMantissa < 0) {
3806 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3807 }
3808
3809 // Cast to unsigned is OK because of check for negative
3810 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3811 // Exponentiation is straight forward
3812 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3813}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003814
3815
3816/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003817 Compute value with signed mantissa and unsigned result. Works with
3818 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003819 */
3820static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3821 int64_t nExponent,
3822 uint64_t *puResult,
3823 fExponentiator pfExp)
3824{
3825 return (*pfExp)(uMantissa, nExponent, puResult);
3826}
3827
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003828#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3829
3830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003831
3832
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003833
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003834static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003835{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003836 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003837
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003838 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003839 const uint8_t *pByte = BigNum.ptr;
3840 size_t uLen = BigNum.len;
3841 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003842 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003843 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003844 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003845 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003846 }
3847
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003848 *pResult = uResult;
3849 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003850}
3851
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003852
Laurence Lundblade887add82020-05-17 05:50:34 -07003853static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003854{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003855 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003856}
3857
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003858
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003859static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003860{
3861 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003862 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3863 if(uError) {
3864 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865 }
3866 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3867 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003869}
3870
3871
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003872static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003873{
3874 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003875 /* The negative integer furthest from zero for a C int64_t is
3876 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3877 negative number in CBOR is computed as -n - 1 where n is the
3878 encoded integer, where n is what is in the variable BigNum. When
3879 converting BigNum to a uint64_t, the maximum value is thus
3880 INT64_MAX, so that when it -n - 1 is applied to it the result will
3881 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003882
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003883 -n - 1 <= INT64_MIN.
3884 -n - 1 <= -INT64_MAX - 1
3885 n <= INT64_MAX.
3886 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003887 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003888 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003889 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003890 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003891
3892 /// Now apply -n - 1. The cast is safe because
3893 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3894 // is the largest positive integer that an int64_t can
3895 // represent. */
3896 *pnResult = -(int64_t)uResult - 1;
3897
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003898 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003899}
3900
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003902
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003903
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003904
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003905/*
3906Convert a integers and floats to an int64_t.
3907
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003908\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003909
Laurence Lundblade93d89472020-10-03 22:30:50 -07003910\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3911 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003912
3913\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3914
Laurence Lundblade93d89472020-10-03 22:30:50 -07003915\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3916 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003917*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003918static QCBORError
3919ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003920{
3921 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003922 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003923 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003924#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003925 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003926 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3927 http://www.cplusplus.com/reference/cmath/llround/
3928 */
3929 // Not interested in FE_INEXACT
3930 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003931 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3932 *pnValue = llround(pItem->val.dfnum);
3933 } else {
3934 *pnValue = lroundf(pItem->val.fnum);
3935 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003936 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3937 // llround() shouldn't result in divide by zero, but catch
3938 // it here in case it unexpectedly does. Don't try to
3939 // distinguish between the various exceptions because it seems
3940 // they vary by CPU, compiler and OS.
3941 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003942 }
3943 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003944 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003945 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003946#else
3947 return QCBOR_ERR_HW_FLOAT_DISABLED;
3948#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003949 break;
3950
3951 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003952 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003953 *pnValue = pItem->val.int64;
3954 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003956 }
3957 break;
3958
3959 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003960 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003961 if(pItem->val.uint64 < INT64_MAX) {
3962 *pnValue = pItem->val.int64;
3963 } else {
3964 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3965 }
3966 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003967 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003968 }
3969 break;
3970
3971 default:
3972 return QCBOR_ERR_UNEXPECTED_TYPE;
3973 }
3974 return QCBOR_SUCCESS;
3975}
3976
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003977
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003978void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003979 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003980 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003981 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003982{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003983 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003984 return;
3985 }
3986
Laurence Lundbladee6430642020-03-14 21:15:44 -07003987 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003988 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3989 if(uError) {
3990 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991 return;
3992 }
3993
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003994 if(pItem) {
3995 *pItem = Item;
3996 }
3997
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003998 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999}
4000
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004001
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004002void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4003 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004004 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004005 int64_t *pnValue,
4006 QCBORItem *pItem)
4007{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004008 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004009 if(pMe->uLastError != QCBOR_SUCCESS) {
4010 return;
4011 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004012
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004013 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004014}
4015
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004016
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004017void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4018 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004019 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004020 int64_t *pnValue,
4021 QCBORItem *pItem)
4022{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004023 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004024 if(pMe->uLastError != QCBOR_SUCCESS) {
4025 return;
4026 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004027
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004028 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029}
4030
4031
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004032/*
4033 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004034
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004035 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004036
Laurence Lundblade93d89472020-10-03 22:30:50 -07004037 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4038 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004039
4040 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4041
Laurence Lundblade93d89472020-10-03 22:30:50 -07004042 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4043 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004045static QCBORError
4046Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048 switch(pItem->uDataType) {
4049
4050 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004051 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004052 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004053 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004055 }
4056 break;
4057
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004058 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004059 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004060 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004061 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004063 }
4064 break;
4065
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004066#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4067 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004070 pItem->val.expAndMantissa.nExponent,
4071 pnValue,
4072 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004073 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004074 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004075 }
4076 break;
4077
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004078 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004079 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004080 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004081 pItem->val.expAndMantissa.nExponent,
4082 pnValue,
4083 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004085 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004086 }
4087 break;
4088
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004089 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004090 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004091 int64_t nMantissa;
4092 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4094 if(uErr) {
4095 return uErr;
4096 }
4097 return ExponentiateNN(nMantissa,
4098 pItem->val.expAndMantissa.nExponent,
4099 pnValue,
4100 Exponentitate10);
4101 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 }
4104 break;
4105
4106 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004108 int64_t nMantissa;
4109 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004110 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4111 if(uErr) {
4112 return uErr;
4113 }
4114 return ExponentiateNN(nMantissa,
4115 pItem->val.expAndMantissa.nExponent,
4116 pnValue,
4117 Exponentitate10);
4118 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004119 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004120 }
4121 break;
4122
4123 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004124 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004125 int64_t nMantissa;
4126 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4128 if(uErr) {
4129 return uErr;
4130 }
4131 return ExponentiateNN(nMantissa,
4132 pItem->val.expAndMantissa.nExponent,
4133 pnValue,
4134 Exponentitate2);
4135 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004136 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004137 }
4138 break;
4139
4140 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004142 int64_t nMantissa;
4143 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004144 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4145 if(uErr) {
4146 return uErr;
4147 }
4148 return ExponentiateNN(nMantissa,
4149 pItem->val.expAndMantissa.nExponent,
4150 pnValue,
4151 Exponentitate2);
4152 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004154 }
4155 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004156#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4157
Laurence Lundbladee6430642020-03-14 21:15:44 -07004158
Laurence Lundbladec4537442020-04-14 18:53:22 -07004159 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004160 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004161}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004162
4163
Laurence Lundbladec4537442020-04-14 18:53:22 -07004164/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004165 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004166 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004167void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004168{
4169 QCBORItem Item;
4170
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004172
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004173 if(pMe->uLastError == QCBOR_SUCCESS) {
4174 // The above conversion succeeded
4175 return;
4176 }
4177
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004178 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004179 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004180 return;
4181 }
4182
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004183 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004184}
4185
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004186
4187/*
4188Public function, see header qcbor/qcbor_decode.h file
4189*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004190void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4191 int64_t nLabel,
4192 uint32_t uConvertTypes,
4193 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194{
4195 QCBORItem Item;
4196
Laurence Lundblade93d89472020-10-03 22:30:50 -07004197 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4198 nLabel,
4199 uConvertTypes,
4200 pnValue,
4201 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004202
4203 if(pMe->uLastError == QCBOR_SUCCESS) {
4204 // The above conversion succeeded
4205 return;
4206 }
4207
4208 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4209 // The above conversion failed in a way that code below can't correct
4210 return;
4211 }
4212
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004213 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004214}
4215
4216
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217/*
4218Public function, see header qcbor/qcbor_decode.h file
4219*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004220void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4221 const char *szLabel,
4222 uint32_t uConvertTypes,
4223 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004224{
4225 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004226 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4227 szLabel,
4228 uConvertTypes,
4229 pnValue,
4230 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004231
4232 if(pMe->uLastError == QCBOR_SUCCESS) {
4233 // The above conversion succeeded
4234 return;
4235 }
4236
4237 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4238 // The above conversion failed in a way that code below can't correct
4239 return;
4240 }
4241
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004242 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004243}
4244
4245
Laurence Lundblade93d89472020-10-03 22:30:50 -07004246static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004247{
4248 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004249 case QCBOR_TYPE_DOUBLE:
4250 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004251#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004252 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004253 // Can't use llround here because it will not convert values
4254 // greater than INT64_MAX and less than UINT64_MAX that
4255 // need to be converted so it is more complicated.
4256 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4257 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4258 if(isnan(pItem->val.dfnum)) {
4259 return QCBOR_ERR_FLOAT_EXCEPTION;
4260 } else if(pItem->val.dfnum < 0) {
4261 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4262 } else {
4263 double dRounded = round(pItem->val.dfnum);
4264 // See discussion in DecodeDateEpoch() for
4265 // explanation of - 0x7ff
4266 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4267 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4268 }
4269 *puValue = (uint64_t)dRounded;
4270 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004271 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004272 if(isnan(pItem->val.fnum)) {
4273 return QCBOR_ERR_FLOAT_EXCEPTION;
4274 } else if(pItem->val.fnum < 0) {
4275 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4276 } else {
4277 float fRounded = roundf(pItem->val.fnum);
4278 // See discussion in DecodeDateEpoch() for
4279 // explanation of - 0x7ff
4280 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4281 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4282 }
4283 *puValue = (uint64_t)fRounded;
4284 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004285 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004286 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4287 // round() and roundf() shouldn't result in exceptions here, but
4288 // catch them to be robust and thorough. Don't try to
4289 // distinguish between the various exceptions because it seems
4290 // they vary by CPU, compiler and OS.
4291 return QCBOR_ERR_FLOAT_EXCEPTION;
4292 }
4293
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004294 } else {
4295 return QCBOR_ERR_UNEXPECTED_TYPE;
4296 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004297#else
4298 return QCBOR_ERR_HW_FLOAT_DISABLED;
4299#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004300 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004301
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004302 case QCBOR_TYPE_INT64:
4303 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4304 if(pItem->val.int64 >= 0) {
4305 *puValue = (uint64_t)pItem->val.int64;
4306 } else {
4307 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4308 }
4309 } else {
4310 return QCBOR_ERR_UNEXPECTED_TYPE;
4311 }
4312 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004313
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314 case QCBOR_TYPE_UINT64:
4315 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4316 *puValue = pItem->val.uint64;
4317 } else {
4318 return QCBOR_ERR_UNEXPECTED_TYPE;
4319 }
4320 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004321
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322 default:
4323 return QCBOR_ERR_UNEXPECTED_TYPE;
4324 }
4325
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004326 return QCBOR_SUCCESS;
4327}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004328
4329
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004330void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004331 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004332 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004333 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004334{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004335 if(pMe->uLastError != QCBOR_SUCCESS) {
4336 return;
4337 }
4338
Laurence Lundbladec4537442020-04-14 18:53:22 -07004339 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004340
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004341 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4342 if(uError) {
4343 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004344 return;
4345 }
4346
Laurence Lundbladea826c502020-05-10 21:07:00 -07004347 if(pItem) {
4348 *pItem = Item;
4349 }
4350
Laurence Lundblade93d89472020-10-03 22:30:50 -07004351 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004352}
4353
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004354
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004355void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004356 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004357 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004358 uint64_t *puValue,
4359 QCBORItem *pItem)
4360{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004361 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004362 if(pMe->uLastError != QCBOR_SUCCESS) {
4363 return;
4364 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004365
Laurence Lundblade93d89472020-10-03 22:30:50 -07004366 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004367}
4368
4369
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004370void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004371 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004372 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004373 uint64_t *puValue,
4374 QCBORItem *pItem)
4375{
4376 if(pMe->uLastError != QCBOR_SUCCESS) {
4377 return;
4378 }
4379
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004380 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004381 if(pMe->uLastError != QCBOR_SUCCESS) {
4382 return;
4383 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004384
Laurence Lundblade93d89472020-10-03 22:30:50 -07004385 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004386}
4387
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004388
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004389/*
4390 Public function, see header qcbor/qcbor_decode.h file
4391*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004392static QCBORError
4393UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004394{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395 switch(pItem->uDataType) {
4396
4397 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004398 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004399 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4400 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004401 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402 }
4403 break;
4404
4405 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4408 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004409 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004410 }
4411 break;
4412
4413#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4414
4415 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004416 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004417 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004418 pItem->val.expAndMantissa.nExponent,
4419 puValue,
4420 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004421 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004422 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004423 }
4424 break;
4425
4426 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004427 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4429 pItem->val.expAndMantissa.nExponent,
4430 puValue,
4431 Exponentitate2);
4432 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004433 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434 }
4435 break;
4436
4437 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004438 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004439 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004440 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004441 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004442 if(uErr != QCBOR_SUCCESS) {
4443 return uErr;
4444 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004445 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004446 pItem->val.expAndMantissa.nExponent,
4447 puValue,
4448 Exponentitate10);
4449 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004450 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004451 }
4452 break;
4453
4454 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004456 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4457 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004458 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459 }
4460 break;
4461
4462 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004463 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004464 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004465 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004466 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 if(uErr != QCBOR_SUCCESS) {
4468 return uErr;
4469 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004470 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471 pItem->val.expAndMantissa.nExponent,
4472 puValue,
4473 Exponentitate2);
4474 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004475 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476 }
4477 break;
4478
4479 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004480 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004481 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4482 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 }
4485 break;
4486#endif
4487 default:
4488 return QCBOR_ERR_UNEXPECTED_TYPE;
4489 }
4490}
4491
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004492
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004493/*
4494 Public function, see header qcbor/qcbor_decode.h file
4495*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004496void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004497{
4498 QCBORItem Item;
4499
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004500 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004501
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004502 if(pMe->uLastError == QCBOR_SUCCESS) {
4503 // The above conversion succeeded
4504 return;
4505 }
4506
4507 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4508 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004509 return;
4510 }
4511
Laurence Lundblade93d89472020-10-03 22:30:50 -07004512 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004513}
4514
Laurence Lundbladec4537442020-04-14 18:53:22 -07004515
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004517 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004518*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004519void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004520 int64_t nLabel,
4521 uint32_t uConvertTypes,
4522 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523{
4524 QCBORItem Item;
4525
Laurence Lundblade93d89472020-10-03 22:30:50 -07004526 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4527 nLabel,
4528 uConvertTypes,
4529 puValue,
4530 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531
4532 if(pMe->uLastError == QCBOR_SUCCESS) {
4533 // The above conversion succeeded
4534 return;
4535 }
4536
4537 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4538 // The above conversion failed in a way that code below can't correct
4539 return;
4540 }
4541
Laurence Lundblade93d89472020-10-03 22:30:50 -07004542 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004543}
4544
4545
4546/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004547 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004549void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004550 const char *szLabel,
4551 uint32_t uConvertTypes,
4552 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553{
4554 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004555 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4556 szLabel,
4557 uConvertTypes,
4558 puValue,
4559 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004560
4561 if(pMe->uLastError == QCBOR_SUCCESS) {
4562 // The above conversion succeeded
4563 return;
4564 }
4565
4566 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4567 // The above conversion failed in a way that code below can't correct
4568 return;
4569 }
4570
Laurence Lundblade93d89472020-10-03 22:30:50 -07004571 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004572}
4573
4574
Laurence Lundblade9b334962020-08-27 10:55:53 -07004575static QCBORError ConvertDouble(const QCBORItem *pItem,
4576 uint32_t uConvertTypes,
4577 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004578{
4579 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004580 case QCBOR_TYPE_FLOAT:
4581#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4582 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4583 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004584 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004585 *pdValue = (double)pItem->val.fnum;
4586 } else {
4587 return QCBOR_ERR_UNEXPECTED_TYPE;
4588 }
4589 }
4590#else
4591 return QCBOR_ERR_HW_FLOAT_DISABLED;
4592#endif
4593 break;
4594
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4597 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 *pdValue = pItem->val.dfnum;
4599 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004600 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601 }
4602 }
4603 break;
4604
4605 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004606#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004608 // A simple cast seems to do the job with no worry of exceptions.
4609 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004610 *pdValue = (double)pItem->val.int64;
4611
4612 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004613 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004614 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004615#else
4616 return QCBOR_ERR_HW_FLOAT_DISABLED;
4617#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618 break;
4619
4620 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004621#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004622 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004623 // A simple cast seems to do the job with no worry of exceptions.
4624 // There will be precision loss for some values.
4625 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004626 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004627 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628 }
4629 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004630#else
4631 return QCBOR_ERR_HW_FLOAT_DISABLED;
4632#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633
4634 default:
4635 return QCBOR_ERR_UNEXPECTED_TYPE;
4636 }
4637
4638 return QCBOR_SUCCESS;
4639}
4640
4641
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004642void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004645 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004646{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004647 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004648 return;
4649 }
4650
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004651 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004652
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004653 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004654 if(uError) {
4655 pMe->uLastError = (uint8_t)uError;
4656 return;
4657 }
4658
4659 if(pItem) {
4660 *pItem = Item;
4661 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004662
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004663 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004664}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004665
Laurence Lundbladec4537442020-04-14 18:53:22 -07004666
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004667void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4668 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670 double *pdValue,
4671 QCBORItem *pItem)
4672{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004673 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004674 if(pMe->uLastError != QCBOR_SUCCESS) {
4675 return;
4676 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004678 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679}
4680
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004681
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004682void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4683 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004684 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 double *pdValue,
4686 QCBORItem *pItem)
4687{
4688 if(pMe->uLastError != QCBOR_SUCCESS) {
4689 return;
4690 }
4691
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004692 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004693 if(pMe->uLastError != QCBOR_SUCCESS) {
4694 return;
4695 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004696
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004697 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004698}
4699
4700
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004701#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004702static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4703{
4704 double dResult;
4705
4706 dResult = 0.0;
4707 const uint8_t *pByte = BigNum.ptr;
4708 size_t uLen = BigNum.len;
4709 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004710 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004711 while(uLen--) {
4712 dResult = (dResult * 256.0) + (double)*pByte++;
4713 }
4714
4715 return dResult;
4716}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004717#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4718
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004719
Laurence Lundblade93d89472020-10-03 22:30:50 -07004720static QCBORError
4721DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004722{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004723#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004724 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004725 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4726
4727 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004728 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004729
4730#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004731 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004732 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004733 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4735 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4736 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004738 }
4739 break;
4740
4741 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004742 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004743 // Underflow gives 0, overflow gives infinity
4744 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4745 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004747 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004748 }
4749 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004750#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751
4752 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004753 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4755 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757 }
4758 break;
4759
4760 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004761 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004762 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004763 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004765 }
4766 break;
4767
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004768#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004770 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004771 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4772 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4773 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004774 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775 }
4776 break;
4777
4778 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004780 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4781 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4782 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004783 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784 }
4785 break;
4786
4787 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004788 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4790 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4791 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004792 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 }
4794 break;
4795
4796 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004798 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004799 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4800 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004801 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 }
4803 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004804#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4805
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 default:
4807 return QCBOR_ERR_UNEXPECTED_TYPE;
4808 }
4809
4810 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004811
4812#else
4813 (void)pItem;
4814 (void)uConvertTypes;
4815 (void)pdValue;
4816 return QCBOR_ERR_HW_FLOAT_DISABLED;
4817#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4818
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004819}
4820
4821
4822/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004823 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004824*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004825void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4826 uint32_t uConvertTypes,
4827 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004828{
4829
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004830 QCBORItem Item;
4831
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004833
4834 if(pMe->uLastError == QCBOR_SUCCESS) {
4835 // The above conversion succeeded
4836 return;
4837 }
4838
4839 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4840 // The above conversion failed in a way that code below can't correct
4841 return;
4842 }
4843
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004845}
4846
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847
4848/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004849 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004851void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4852 int64_t nLabel,
4853 uint32_t uConvertTypes,
4854 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004855{
4856 QCBORItem Item;
4857
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859
4860 if(pMe->uLastError == QCBOR_SUCCESS) {
4861 // The above conversion succeeded
4862 return;
4863 }
4864
4865 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4866 // The above conversion failed in a way that code below can't correct
4867 return;
4868 }
4869
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004870 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871}
4872
4873
4874/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004875 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004877void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4878 const char *szLabel,
4879 uint32_t uConvertTypes,
4880 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881{
4882 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004883 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884
4885 if(pMe->uLastError == QCBOR_SUCCESS) {
4886 // The above conversion succeeded
4887 return;
4888 }
4889
4890 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4891 // The above conversion failed in a way that code below can't correct
4892 return;
4893 }
4894
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004895 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004896}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004897
4898
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004899
4900
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004901#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004902static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4903{
4904 while((uInt & 0xff00000000000000UL) == 0) {
4905 uInt = uInt << 8;
4906 };
4907
4908 UsefulOutBuf UOB;
4909
4910 UsefulOutBuf_Init(&UOB, Buffer);
4911
4912 while(uInt) {
4913 const uint64_t xx = uInt & 0xff00000000000000UL;
4914 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4915 uInt = uInt << 8;
4916 (void)xx;
4917 }
4918
4919 return UsefulOutBuf_OutUBuf(&UOB);
4920}
4921
4922
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004923static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4924 TagSpecification TagSpec,
4925 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004926{
4927 QCBORError uErr;
4928 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004929 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004930 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004931 if(uErr != QCBOR_SUCCESS) {
4932 goto Done;
4933 }
4934
4935 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4936 break; // Successful exit. Moving on to finish decoding.
4937 }
4938
4939 // The item is an array, which means an undecoded
4940 // mantissa and exponent, so decode it. It will then
4941 // have a different type and exit the loop if.
4942 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4943 if(uErr != QCBOR_SUCCESS) {
4944 goto Done;
4945 }
4946
4947 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004948 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004949 }
4950Done:
4951 return uErr;
4952}
4953
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004954
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004955static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004956 TagSpecification TagSpec,
4957 QCBORItem *pItem,
4958 int64_t *pnMantissa,
4959 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004960{
4961 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004962
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004963 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004964 if(uErr != QCBOR_SUCCESS) {
4965 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004966 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004967
Laurence Lundblade9b334962020-08-27 10:55:53 -07004968 switch (pItem->uDataType) {
4969
4970 case QCBOR_TYPE_DECIMAL_FRACTION:
4971 case QCBOR_TYPE_BIGFLOAT:
4972 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4973 *pnExponent = pItem->val.expAndMantissa.nExponent;
4974 break;
4975
4976 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4977 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4978 *pnExponent = pItem->val.expAndMantissa.nExponent;
4979 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4980 break;
4981
4982 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4983 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4984 *pnExponent = pItem->val.expAndMantissa.nExponent;
4985 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4986 break;
4987
4988 default:
4989 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4990 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004991
4992 Done:
4993 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004994}
4995
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004996
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004997static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004998 TagSpecification TagSpec,
4999 QCBORItem *pItem,
5000 UsefulBuf BufferForMantissa,
5001 UsefulBufC *pMantissa,
5002 bool *pbIsNegative,
5003 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005004{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005005 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005006
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005007 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005008 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005009 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005010 }
5011
5012 uint64_t uMantissa;
5013
5014 switch (pItem->uDataType) {
5015
5016 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005017 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005018 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5019 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5020 *pbIsNegative = false;
5021 } else {
5022 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5023 *pbIsNegative = true;
5024 }
5025 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5026 *pnExponent = pItem->val.expAndMantissa.nExponent;
5027 break;
5028
5029 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005030 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005031 *pnExponent = pItem->val.expAndMantissa.nExponent;
5032 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5033 *pbIsNegative = false;
5034 break;
5035
5036 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005037 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005038 *pnExponent = pItem->val.expAndMantissa.nExponent;
5039 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5040 *pbIsNegative = true;
5041 break;
5042
5043 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005044 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005045 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005046
5047Done:
5048 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005049}
5050
5051
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005052/*
5053 Public function, see header qcbor/qcbor_decode.h file
5054*/
5055void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5056 uint8_t uTagRequirement,
5057 int64_t *pnMantissa,
5058 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005059{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005060 if(pMe->uLastError != QCBOR_SUCCESS) {
5061 return;
5062 }
5063
5064 QCBORItem Item;
5065 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5066 if(uError) {
5067 pMe->uLastError = (uint8_t)uError;
5068 return;
5069 }
5070
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005071 const TagSpecification TagSpec =
5072 {
5073 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005074 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5075 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5076 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005077 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005078
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005079 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005080}
5081
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005082
5083/*
5084 Public function, see header qcbor/qcbor_decode.h file
5085*/
5086void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005087 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005088 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005089 int64_t *pnMantissa,
5090 int64_t *pnExponent)
5091{
5092 if(pMe->uLastError != QCBOR_SUCCESS) {
5093 return;
5094 }
5095
5096 QCBORItem Item;
5097 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5098
5099 const TagSpecification TagSpec =
5100 {
5101 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005102 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5103 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5104 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005105 };
5106
5107 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5108}
5109
5110
5111/*
5112 Public function, see header qcbor/qcbor_decode.h file
5113*/
5114void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005115 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005116 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005117 int64_t *pnMantissa,
5118 int64_t *pnExponent)
5119{
5120 if(pMe->uLastError != QCBOR_SUCCESS) {
5121 return;
5122 }
5123
5124 QCBORItem Item;
5125 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5126
5127 const TagSpecification TagSpec =
5128 {
5129 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005130 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5131 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5132 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005133 };
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,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005163 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5164 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5165 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005166 };
5167
Laurence Lundblade93d89472020-10-03 22:30:50 -07005168 ProcessMantissaAndExponentBig(pMe,
5169 TagSpec,
5170 &Item,
5171 MantissaBuffer,
5172 pMantissa,
5173 pbMantissaIsNegative,
5174 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005175}
5176
5177
5178/*
5179 Public function, see header qcbor/qcbor_decode.h file
5180*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005181void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005182 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005183 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005184 UsefulBuf BufferForMantissa,
5185 UsefulBufC *pMantissa,
5186 bool *pbIsNegative,
5187 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005188{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189 if(pMe->uLastError != QCBOR_SUCCESS) {
5190 return;
5191 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005192
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005193 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005194 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005195 if(pMe->uLastError != QCBOR_SUCCESS) {
5196 return;
5197 }
5198
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005199 const TagSpecification TagSpec =
5200 {
5201 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005202 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5203 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5204 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005205 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005206
Laurence Lundblade93d89472020-10-03 22:30:50 -07005207 ProcessMantissaAndExponentBig(pMe,
5208 TagSpec,
5209 &Item,
5210 BufferForMantissa,
5211 pMantissa,
5212 pbIsNegative,
5213 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005214}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005215
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005216
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005217/*
5218 Public function, see header qcbor/qcbor_decode.h file
5219*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005220void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005221 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005222 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005223 UsefulBuf BufferForMantissa,
5224 UsefulBufC *pMantissa,
5225 bool *pbIsNegative,
5226 int64_t *pnExponent)
5227{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005228 if(pMe->uLastError != QCBOR_SUCCESS) {
5229 return;
5230 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005231
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005232 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005233 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5234 if(pMe->uLastError != QCBOR_SUCCESS) {
5235 return;
5236 }
5237
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005238 const TagSpecification TagSpec =
5239 {
5240 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005241 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5242 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5243 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005244 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005245
5246 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5247}
5248
5249
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005250/*
5251 Public function, see header qcbor/qcbor_decode.h file
5252*/
5253void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5254 uint8_t uTagRequirement,
5255 int64_t *pnMantissa,
5256 int64_t *pnExponent)
5257{
5258 if(pMe->uLastError != QCBOR_SUCCESS) {
5259 return;
5260 }
5261
5262 QCBORItem Item;
5263 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5264 if(uError) {
5265 pMe->uLastError = (uint8_t)uError;
5266 return;
5267 }
5268 const TagSpecification TagSpec =
5269 {
5270 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005271 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5272 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5273 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005274 };
5275
5276 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5277}
5278
5279
5280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
5283void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005285 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005286 int64_t *pnMantissa,
5287 int64_t *pnExponent)
5288{
5289 if(pMe->uLastError != QCBOR_SUCCESS) {
5290 return;
5291 }
5292
5293 QCBORItem Item;
5294 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5295 if(pMe->uLastError != QCBOR_SUCCESS) {
5296 return;
5297 }
5298
5299 const TagSpecification TagSpec =
5300 {
5301 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005302 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5303 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5304 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005305 };
5306
5307 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5308}
5309
5310
5311/*
5312 Public function, see header qcbor/qcbor_decode.h file
5313*/
5314void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005315 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005316 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317 int64_t *pnMantissa,
5318 int64_t *pnExponent)
5319{
5320 if(pMe->uLastError != QCBOR_SUCCESS) {
5321 return;
5322 }
5323
5324 QCBORItem Item;
5325 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5326 if(pMe->uLastError != QCBOR_SUCCESS) {
5327 return;
5328 }
5329
5330 const TagSpecification TagSpec =
5331 {
5332 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005333 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5334 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5335 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005336 };
5337
5338 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5339}
5340
5341
5342/*
5343 Public function, see header qcbor/qcbor_decode.h file
5344*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005345void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5346 uint8_t uTagRequirement,
5347 UsefulBuf MantissaBuffer,
5348 UsefulBufC *pMantissa,
5349 bool *pbMantissaIsNegative,
5350 int64_t *pnExponent)
5351{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005352 if(pMe->uLastError != QCBOR_SUCCESS) {
5353 return;
5354 }
5355
5356 QCBORItem Item;
5357 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5358 if(uError) {
5359 pMe->uLastError = (uint8_t)uError;
5360 return;
5361 }
5362
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005363 const TagSpecification TagSpec =
5364 {
5365 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005366 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5367 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5368 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005369 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005370
5371 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005372}
5373
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005374
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005375/*
5376 Public function, see header qcbor/qcbor_decode.h file
5377*/
5378void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005379 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005380 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005381 UsefulBuf BufferForMantissa,
5382 UsefulBufC *pMantissa,
5383 bool *pbIsNegative,
5384 int64_t *pnExponent)
5385{
5386 if(pMe->uLastError != QCBOR_SUCCESS) {
5387 return;
5388 }
5389
5390 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005391 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5392 if(pMe->uLastError != QCBOR_SUCCESS) {
5393 return;
5394 }
5395
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005396 const TagSpecification TagSpec =
5397 {
5398 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005399 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5400 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5401 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005402 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005403
Laurence Lundblade93d89472020-10-03 22:30:50 -07005404 ProcessMantissaAndExponentBig(pMe,
5405 TagSpec,
5406 &Item,
5407 BufferForMantissa,
5408 pMantissa,
5409 pbIsNegative,
5410 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005411}
5412
5413
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005414/*
5415 Public function, see header qcbor/qcbor_decode.h file
5416*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005417void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005418 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005419 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005420 UsefulBuf BufferForMantissa,
5421 UsefulBufC *pMantissa,
5422 bool *pbIsNegative,
5423 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005424{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005425 if(pMe->uLastError != QCBOR_SUCCESS) {
5426 return;
5427 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005428
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005429 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005430 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5431 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005432 return;
5433 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005434
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005435 const TagSpecification TagSpec =
5436 {
5437 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005438 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5439 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5440 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005441 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005442
Laurence Lundblade93d89472020-10-03 22:30:50 -07005443 ProcessMantissaAndExponentBig(pMe,
5444 TagSpec,
5445 &Item,
5446 BufferForMantissa,
5447 pMantissa,
5448 pbIsNegative,
5449 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005450}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005451
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005452#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */