blob: 64a86f7e314bd3a8b3cb23c8d602b2ec601be2de [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 Lundbladea8edadb2020-06-27 22:35:37 -070096 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
97 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700101 */
102
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700103
104inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700105DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700106{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700107 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700108 /*
109 Limit in DecodeNesting_Descend against more than
110 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
111 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700112 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113}
114
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700115
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700116inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700117DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700118{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700119 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120 /*
121 Limit in DecodeNesting_Descend against more than
122 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
123 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700124 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700128static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700129DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
131 return pNesting->pCurrentBounded->u.ma.uStartOffset;
132}
133
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700134
Laurence Lundblade085d7952020-07-24 10:26:30 -0700135static inline bool
136DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
137{
138 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700150 return true;
151 } else {
152 return false;
153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154}
155
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700156
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700157inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159{
160 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700164 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700165 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166 return false;
167 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700168 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700169 return true;
170}
171
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700172
Laurence Lundblade642282a2020-06-23 12:00:33 -0700173inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700174DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700175{
176 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700178 return true;
179 }
180 return false;
181}
182
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700183
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700184inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185{
186 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
187 return true;
188 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700189 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190 return true;
191 }
192 return false;
193}
194
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700195
Laurence Lundblade085d7952020-07-24 10:26:30 -0700196inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700197{
198 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700199 /*
200 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
201 larger than DecodeNesting_EnterBoundedMode which keeps it less than
202 uin32_t so the cast is safe.
203 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700204 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700205
206 if(bIsEmpty) {
207 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
208 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209}
210
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700211
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700214 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700215}
216
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700217
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220{
221 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700222 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
225 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700226 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700229 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
230 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700233 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700234 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700238 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700239 return true;
240}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700241
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700244DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700245{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700246 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700247 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
248 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700249 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700250 return false;
251 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700252}
253
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700254
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255inline static bool
256DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700257{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
259 return true;
260 } else {
261 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263}
264
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700265
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700266inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700267DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700268{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700270 return false;
271 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700272
273 if(pNesting->pCurrentBounded->uLevelType != uType) {
274 return false;
275 }
276
277 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278}
279
Laurence Lundblade02625d42020-06-25 14:41:41 -0700280
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700281inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700282DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700283{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700284 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700286}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700287
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700288
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700289inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700290DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
291{
292 // Only call on a defnite length array / map
293 pNesting->pCurrent->u.ma.uCountCursor++;
294}
295
296
297inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700298DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
299{
300 pNesting->pCurrent--;
301}
302
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303
304static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700305DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700306{
307 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700308 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700309 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700310 }
311
312 // The actual descend
313 pNesting->pCurrent++;
314
315 pNesting->pCurrent->uLevelType = uType;
316
317 return QCBOR_SUCCESS;
318}
319
320
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700321inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700322DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700323{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700324 /*
325 Should only be called on map/array.
326
327 Have descended into this before this is called. The job here is
328 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700329
330 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
331 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700332 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700333 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700334 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700335 }
336
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700337 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700338
339 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700340
341 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700342}
343
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700344
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700345inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700346DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 uint8_t uQCBORType,
348 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700351
352 if(uCount == 0) {
353 // Nothing to do for empty definite lenth arrays. They are just are
354 // effectively the same as an item that is not a map or array
355 goto Done;
356 // Empty indefinite length maps and arrays are handled elsewhere
357 }
358
359 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700360 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
361 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700362 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363 goto Done;
364 }
365
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700366 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700368 goto Done;
369 }
370
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700371 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700372 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
373 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700374
375 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700376
377Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700378 return uError;;
379}
380
381
382static inline void
383DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
384{
385 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
386}
387
388
389static inline void
390DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
391{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700392 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 pNesting->pCurrentBounded--;
394 if(DecodeNesting_IsCurrentBounded(pNesting)) {
395 break;
396 }
397 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700398}
399
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700400static inline void
401DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
402{
403 pNesting->pCurrent = pNesting->pCurrentBounded;
404}
405
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700406
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700409 uint32_t uEndOffset,
410 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700411{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700414 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700416 goto Done;
417 }
418
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700420 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
421 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424 pNesting->pCurrentBounded = pNesting->pCurrent;
425
426Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427 return uError;;
428}
429
Laurence Lundbladed0304932020-06-27 10:59:38 -0700430
431static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700432DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700433{
434 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435}
436
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700437
Laurence Lundbladeee851742020-01-08 08:37:05 -0800438inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700439DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700441 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
443 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444}
445
446
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700447inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700448DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700449{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700450 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700451 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700452 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453}
454
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700455
Laurence Lundblade02625d42020-06-25 14:41:41 -0700456static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700457DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700458{
459 *pNesting = *pSave;
460}
461
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462
Laurence Lundblade02625d42020-06-25 14:41:41 -0700463static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700464DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700465{
466 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
467}
468
469
Laurence Lundblade02625d42020-06-25 14:41:41 -0700470static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700471DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700472{
473 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
474}
475
476
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700477
Laurence Lundbladeee851742020-01-08 08:37:05 -0800478/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800479 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
480
481 The following four functions are pretty wrappers for invocation of
482 the string allocator supplied by the caller.
483
Laurence Lundbladeee851742020-01-08 08:37:05 -0800484 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485
Laurence Lundbladeee851742020-01-08 08:37:05 -0800486static inline void
487StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800488{
489 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
490}
491
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492// StringAllocator_Reallocate called with pMem NULL is
493// equal to StringAllocator_Allocate()
494static inline UsefulBuf
495StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
496 void *pMem,
497 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800498{
499 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
500}
501
Laurence Lundbladeee851742020-01-08 08:37:05 -0800502static inline UsefulBuf
503StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800504{
505 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
506}
507
Laurence Lundbladeee851742020-01-08 08:37:05 -0800508static inline void
509StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800510{
511 if(pMe->pfAllocator) {
512 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
513 }
514}
515
516
517
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518/*===========================================================================
519 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800521 See qcbor/qcbor_decode.h for definition of the object
522 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524/*
525 Public function, see header file
526 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527void QCBORDecode_Init(QCBORDecodeContext *me,
528 UsefulBufC EncodedCBOR,
529 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530{
531 memset(me, 0, sizeof(QCBORDecodeContext));
532 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533 // Don't bother with error check on decode mode. If a bad value is
534 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700535 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700536 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700537 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700538 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700539 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540}
541
542
543/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700544 Public function, see header file
545 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
547 QCBORStringAllocate pfAllocateFunction,
548 void *pAllocateContext,
549 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800551 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
552 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
553 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700554}
555
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556
557/*
558 Public function, see header file
559 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700560void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700562{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700563 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700564 (void)pMe;
565 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700566}
567
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700568
569/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570 This decodes the fundamental part of a CBOR data item, the type and
571 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800572
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700573 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800574
Laurence Lundbladeee851742020-01-08 08:37:05 -0800575 This does the network->host byte order conversion. The conversion
576 here also results in the conversion for floats in addition to that
577 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800578
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700579 This returns:
580 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800582 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800583 tags and floats and length for strings and arrays
584
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800586 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800587
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800588 The int type is preferred to uint8_t for some variables as this
589 avoids integer promotions, can reduce code size and makes
590 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700591
592 @retval QCBOR_ERR_UNSUPPORTED
593
594 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800596inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
597 int *pnMajorType,
598 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800599 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700601 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800602
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800604 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700606 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800607 const int nTmpMajorType = nInitialByte >> 5;
608 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800610 // Where the number or argument accumulates
611 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700614 // Need to get 1,2,4 or 8 additional argument bytes. Map
615 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800616 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800617
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618 // Loop getting all the bytes in the argument
619 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800621 // This shift and add gives the endian conversion
622 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
623 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // The reserved and thus-far unused additional info values
626 nReturn = QCBOR_ERR_UNSUPPORTED;
627 goto Done;
628 } else {
629 // Less than 24, additional info is argument or 31, an indefinite length
630 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 if(UsefulInputBuf_GetError(pUInBuf)) {
635 nReturn = QCBOR_ERR_HIT_END;
636 goto Done;
637 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 // All successful if we got here.
640 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800644
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645Done:
646 return nReturn;
647}
648
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800651 CBOR doesn't explicitly specify two's compliment for integers but all
652 CPUs use it these days and the test vectors in the RFC are so. All
653 integers in the CBOR structure are positive and the major type
654 indicates positive or negative. CBOR can express positive integers
655 up to 2^x - 1 where x is the number of bits and negative integers
656 down to 2^x. Note that negative numbers can be one more away from
657 zero than positive. Stdint, as far as I can tell, uses two's
658 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800659
Laurence Lundblade9b334962020-08-27 10:55:53 -0700660 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800661 used carefully here, and in particular why it isn't used in the interface.
662 Also see
663 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
664
665 Int is used for values that need less than 16-bits and would be subject
666 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667
668 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800670inline static QCBORError
671DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700673 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800674
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700675 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
676 if (uNumber <= INT64_MAX) {
677 pDecodedItem->val.int64 = (int64_t)uNumber;
678 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680 } else {
681 pDecodedItem->val.uint64 = uNumber;
682 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 }
685 } else {
686 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 // CBOR's representation of negative numbers lines up with the
688 // two-compliment representation. A negative integer has one
689 // more in range than a positive integer. INT64_MIN is
690 // equal to (-INT64_MAX) - 1.
691 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 } else {
695 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000696 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 nReturn = QCBOR_ERR_INT_OVERFLOW;
698 }
699 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 return nReturn;
702}
703
704// Make sure #define value line up as DecodeSimple counts on this.
705#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
706#error QCBOR_TYPE_FALSE macro value wrong
707#endif
708
709#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
710#error QCBOR_TYPE_TRUE macro value wrong
711#endif
712
713#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
714#error QCBOR_TYPE_NULL macro value wrong
715#endif
716
717#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
718#error QCBOR_TYPE_UNDEF macro value wrong
719#endif
720
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700721#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
722#error QCBOR_TYPE_BREAK macro value wrong
723#endif
724
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
726#error QCBOR_TYPE_DOUBLE macro value wrong
727#endif
728
729#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
730#error QCBOR_TYPE_FLOAT macro value wrong
731#endif
732
733/*
734 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700735
736 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
737
738 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800740inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700743 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700745 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700747 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800749
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800751 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
752 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700754 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700755#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700756 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700757 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700758 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700759 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
760 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700761#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700762 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700763#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700764 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700765 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700766 // Single precision is normally returned as a double
767 // since double is widely supported, there is no loss of
768 // precision, it makes it easy for the caller in
769 // most cases and it can be converted back to single
770 // with no loss of precision
771 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700772 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700773 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 {
775 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
776#ifndef QCBOR_DISABLE_FLOAT_HW_USE
777 // In the normal case, use HW to convert float to double.
778 pDecodedItem->val.dfnum = (double)f;
779 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700780#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700781 // Use of float HW is disabled, return as a float.
782 pDecodedItem->val.fnum = f;
783 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
784
785 // IEEE754_FloatToDouble() could be used here to return
786 // as a double, but it adds object code and most likely
787 // anyone disabling FLOAT HW use doesn't care about
788 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700789#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700790 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700792
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700793 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700794 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700795 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700796 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 case CBOR_SIMPLEV_FALSE: // 20
799 case CBOR_SIMPLEV_TRUE: // 21
800 case CBOR_SIMPLEV_NULL: // 22
801 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700802 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800804
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 case CBOR_SIMPLEV_ONEBYTE: // 24
806 if(uNumber <= CBOR_SIMPLE_BREAK) {
807 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700808 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 goto Done;
810 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800811 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800813
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700814 default: // 0-19
815 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800816 /*
817 DecodeTypeAndNumber will make uNumber equal to
818 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
819 safe because the 2, 4 and 8 byte lengths of uNumber are in
820 the double/float cases above
821 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 pDecodedItem->val.uSimple = (uint8_t)uNumber;
823 break;
824 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826Done:
827 return nReturn;
828}
829
830
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530832 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700833
834 @retval QCBOR_ERR_HIT_END
835
836 @retval QCBOR_ERR_STRING_ALLOCATE
837
838 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800840inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
841 int nMajorType,
842 uint64_t uStrLen,
843 UsefulInputBuf *pUInBuf,
844 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700846 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
849 // This check makes the casts to size_t below safe.
850
851 // 4 bytes less than the largest sizeof() so this can be tested by
852 // putting a SIZE_MAX length in the CBOR test input (no one will
853 // care the limit on strings is 4 bytes shorter).
854 if(uStrLen > SIZE_MAX-4) {
855 nReturn = QCBOR_ERR_STRING_TOO_LONG;
856 goto Done;
857 }
858
859 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530860 if(UsefulBuf_IsNULLC(Bytes)) {
861 // Failed to get the bytes for this string item
862 nReturn = QCBOR_ERR_HIT_END;
863 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530865
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800866 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530869 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700870 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530871 goto Done;
872 }
873 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 } else {
876 // Normal case with no string allocator
877 pDecodedItem->val.string = Bytes;
878 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800879 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800880 // Cast because ternary operator causes promotion to integer
881 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
882 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 return nReturn;
886}
887
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700888
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700890
891
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892
893
Laurence Lundbladeee851742020-01-08 08:37:05 -0800894// Make sure the constants align as this is assumed by
895// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700896#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
897#error QCBOR_TYPE_ARRAY value not lined up with major type
898#endif
899#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
900#error QCBOR_TYPE_MAP value not lined up with major type
901#endif
902
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700903/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800904 This gets a single data item and decodes it including preceding
905 optional tagging. This does not deal with arrays and maps and nesting
906 except to decode the data item introducing them. Arrays and maps are
907 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladeee851742020-01-08 08:37:05 -0800909 Errors detected here include: an array that is too long to decode,
910 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700911
912 @retval QCBOR_ERR_UNSUPPORTED
913
914 @retval QCBOR_ERR_HIT_END
915
916 @retval QCBOR_ERR_INT_OVERFLOW
917
918 @retval QCBOR_ERR_STRING_ALLOCATE
919
920 @retval QCBOR_ERR_STRING_TOO_LONG
921
922 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
923
924 @retval QCBOR_ERR_BAD_TYPE_7
925
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700926 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800927static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
928 QCBORItem *pDecodedItem,
929 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700931 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladeee851742020-01-08 08:37:05 -0800933 /*
934 Get the major type and the number. Number could be length of more
935 bytes or the value depending on the major type nAdditionalInfo is
936 an encoding of the length of the uNumber and is needed to decode
937 floats and doubles
938 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800939 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800941 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800942
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700943 memset(pDecodedItem, 0, sizeof(QCBORItem));
944
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800945 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundbladeee851742020-01-08 08:37:05 -0800947 // Error out here if we got into trouble on the type and number. The
948 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700949 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladeee851742020-01-08 08:37:05 -0800953 // At this point the major type and the value are valid. We've got
954 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
957 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700959 nReturn = QCBOR_ERR_BAD_INT;
960 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800961 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700962 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
966 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800967 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
968 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
969 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
970 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530971 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700972 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 }
975 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
978 case CBOR_MAJOR_TYPE_MAP: // Major type 5
979 // Record the number of items in the array or map
980 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700981 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 goto Done;
983 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700985 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 // type conversion OK because of check above
988 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800990 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800991 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
992 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800994
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700997 nReturn = QCBOR_ERR_BAD_INT;
998 } else {
999 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001000 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001001 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 case CBOR_MAJOR_TYPE_SIMPLE:
1005 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001006 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladeee851742020-01-08 08:37:05 -08001009 default:
1010 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 nReturn = QCBOR_ERR_UNSUPPORTED;
1012 break;
1013 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001014
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015Done:
1016 return nReturn;
1017}
1018
1019
1020
1021/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001022 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001023 individual chunk items together into one QCBORItem using the string
1024 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301026 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001027
1028 @retval QCBOR_ERR_UNSUPPORTED
1029
1030 @retval QCBOR_ERR_HIT_END
1031
1032 @retval QCBOR_ERR_INT_OVERFLOW
1033
1034 @retval QCBOR_ERR_STRING_ALLOCATE
1035
1036 @retval QCBOR_ERR_STRING_TOO_LONG
1037
1038 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1039
1040 @retval QCBOR_ERR_BAD_TYPE_7
1041
1042 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1043
1044 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001046static inline QCBORError
1047GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001049 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001050
1051 // Get pointer to string allocator. First use is to pass it to
1052 // GetNext_Item() when option is set to allocate for *every* string.
1053 // Second use here is to allocate space to coallese indefinite
1054 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001055 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1056 &(me->StringAllocator) :
1057 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001058
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001059 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001060 nReturn = GetNext_Item(&(me->InBuf),
1061 pDecodedItem,
1062 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063 if(nReturn) {
1064 goto Done;
1065 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001066
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001067 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301068 // code in this function from here down can be eliminated. Run tests, except
1069 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001071 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001072 const uint8_t uStringType = pDecodedItem->uDataType;
1073 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074 goto Done; // no need to do any work here on non-string types
1075 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301078 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001079 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301082 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001083 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1085 goto Done;
1086 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001087
Laurence Lundblade4b270642020-08-14 12:53:07 -07001088 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001089 UsefulBufC FullString = NULLUsefulBufC;
1090
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001092 // Get item for next chunk
1093 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001094 // NULL string allocator passed here. Do not need to allocate
1095 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001096 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001097 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001098 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001100
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301101 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001102 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001103 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301105 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 break;
1107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001109 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301110 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001111 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001112 if(StringChunkItem.uDataType != uStringType ||
1113 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001114 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 break;
1116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301118 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001119 // The first time throurgh FullString.ptr is NULL and this is
1120 // equivalent to StringAllocator_Allocate()
1121 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1122 UNCONST_POINTER(FullString.ptr),
1123 FullString.len + StringChunkItem.val.string.len);
1124
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301126 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001127 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001128 break;
1129 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001131 // Copy new string chunk at the end of string so far.
1132 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001135 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1136 // Getting the item failed, clean up the allocated memory
1137 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001140Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141 return nReturn;
1142}
1143
Laurence Lundblade9b334962020-08-27 10:55:53 -07001144static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001145 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001146 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001147 } else if(uTagVal == CBOR_TAG_INVALID16) {
1148 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001149 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001150 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 return me->auMappedTags[x];
1152 }
1153}
1154
Laurence Lundblade9b334962020-08-27 10:55:53 -07001155
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001156/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001157 Gets all optional tag data items preceding a data item that is not an
1158 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001159
1160 @retval QCBOR_ERR_UNSUPPORTED
1161
1162 @retval QCBOR_ERR_HIT_END
1163
1164 @retval QCBOR_ERR_INT_OVERFLOW
1165
1166 @retval QCBOR_ERR_STRING_ALLOCATE
1167
1168 @retval QCBOR_ERR_STRING_TOO_LONG
1169
1170 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1171
1172 @retval QCBOR_ERR_BAD_TYPE_7
1173
1174 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1175
1176 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1177
1178 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001180static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001181GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001182{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001183 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1184 CBOR_TAG_INVALID16,
1185 CBOR_TAG_INVALID16,
1186 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001187
Laurence Lundblade9b334962020-08-27 10:55:53 -07001188 QCBORError uReturn = QCBOR_SUCCESS;
1189
Laurence Lundblade59289e52019-12-30 13:44:37 -08001190 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001192 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1193 if(uErr != QCBOR_SUCCESS) {
1194 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001195 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundblade9b334962020-08-27 10:55:53 -07001198 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001199 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001200 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001201 break;
1202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade9b334962020-08-27 10:55:53 -07001204 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1205 // No room in the tag list
1206 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1207 // Continue on to get all tags on this item even though
1208 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001209 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001210 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001211 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001212 // Slide tags over one in the array to make room at index 0
1213 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1214 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001215 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001218 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001220 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001221 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001222 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001223 break;
1224 }
1225 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1226 break;
1227 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001228 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1230 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001231 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1232 // Continue on to get all tags on this item even though
1233 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001234 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001235 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001236 }
1237
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001238 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001241
1242 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001243 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001244 }
1245 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001248 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001249}
1250
1251
1252/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001253 This layer takes care of map entries. It combines the label and data
1254 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001255
1256 @retval QCBOR_ERR_UNSUPPORTED
1257
1258 @retval QCBOR_ERR_HIT_END
1259
1260 @retval QCBOR_ERR_INT_OVERFLOW
1261
1262 @retval QCBOR_ERR_STRING_ALLOCATE
1263
1264 @retval QCBOR_ERR_STRING_TOO_LONG
1265
1266 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1267
1268 @retval QCBOR_ERR_BAD_TYPE_7
1269
1270 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1271
1272 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1273
1274 @retval QCBOR_ERR_TOO_MANY_TAGS
1275
1276 @retval QCBOR_ERR_MAP_LABEL_TYPE
1277
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001278 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001279 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001280static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001283 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001285 if(nReturn)
1286 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001287
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001288 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001289 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001290 goto Done;
1291 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001292
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001293 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1294 // In a map and caller wants maps decoded, not treated as arrays
1295
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001296 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001297 // If in a map and the right decoding mode, get the label
1298
Laurence Lundbladeee851742020-01-08 08:37:05 -08001299 // Save label in pDecodedItem and get the next which will
1300 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001301 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001303 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001304 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001305 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001306
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301307 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001308
1309 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1310 // strings are always good labels
1311 pDecodedItem->label.string = LabelItem.val.string;
1312 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1313 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001314 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001315 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1316 goto Done;
1317 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1318 pDecodedItem->label.int64 = LabelItem.val.int64;
1319 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1320 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1321 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1322 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1323 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1324 pDecodedItem->label.string = LabelItem.val.string;
1325 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1326 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1327 } else {
1328 // label is not an int or a string. It is an arrray
1329 // or a float or such and this implementation doesn't handle that.
1330 // Also, tags on labels are ignored.
1331 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1332 goto Done;
1333 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001334 }
1335 } else {
1336 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001337 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001338 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001339 goto Done;
1340 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001341 // Decoding a map as an array
1342 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001343 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1344 // Cast is needed because of integer promotion
1345 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001346 }
1347 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001348
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001349Done:
1350 return nReturn;
1351}
1352
1353
Laurence Lundblade02625d42020-06-25 14:41:41 -07001354/*
1355 See if next item is a CBOR break. If it is, it is consumed,
1356 if not it is not consumed.
1357*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001358static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001359NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1360{
1361 *pbNextIsBreak = false;
1362 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001363 QCBORItem Peek;
1364 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1365 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1366 if(uReturn != QCBOR_SUCCESS) {
1367 return uReturn;
1368 }
1369 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001370 // It is not a break, rewind so it can be processed normally.
1371 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001372 } else {
1373 *pbNextIsBreak = true;
1374 }
1375 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001376
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001377 return QCBOR_SUCCESS;
1378}
1379
1380
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001381/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001382 An item was just consumed, now figure out if it was the
1383 end of an array or map that can be closed out. That
1384 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001385*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001386static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001387{
1388 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001389
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 /* This loops ascending nesting levels as long as there is ascending to do */
1391 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1392
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001393 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001394 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001395 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1396 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001397 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001398 break;
1399 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001400 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001402 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001403 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001404 bool bIsBreak = false;
1405 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1406 if(uReturn != QCBOR_SUCCESS) {
1407 goto Done;
1408 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001409
1410 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001411 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001412 break;
1413 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001414
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001415 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001416 /*
1417 Break occurred inside a bstr-wrapped CBOR or
1418 in the top level sequence. This is always an
1419 error because neither are an indefinte length
1420 map/array.
1421 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001422 uReturn = QCBOR_ERR_BAD_BREAK;
1423 goto Done;
1424 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001425
Laurence Lundblade02625d42020-06-25 14:41:41 -07001426 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001427 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001428
Laurence Lundblade02625d42020-06-25 14:41:41 -07001429 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001430
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001431 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001432 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001434 if(bMarkEnd) {
1435 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001436 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001437
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001438 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001439 break;
1440 }
1441
1442 /* Finally, actually ascend one level. */
1443 DecodeNesting_Ascend(&(pMe->nesting));
1444 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001445
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001446 uReturn = QCBOR_SUCCESS;
1447
1448Done:
1449 return uReturn;
1450}
1451
1452
1453/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001454 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1456 indefinte length maps and arrays by looking at the item count or
1457 finding CBOR breaks. It detects the ends of the top-level sequence
1458 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001459
1460 @retval QCBOR_ERR_UNSUPPORTED X
1461
1462 @retval QCBOR_ERR_HIT_END
1463
1464 @retval QCBOR_ERR_INT_OVERFLOW X
1465
1466 @retval QCBOR_ERR_STRING_ALLOCATE
1467
1468 @retval QCBOR_ERR_STRING_TOO_LONG
1469
1470 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1471
1472 @retval QCBOR_ERR_BAD_TYPE_7 X
1473
1474 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1475
1476 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1477
1478 @retval QCBOR_ERR_TOO_MANY_TAGS
1479
1480 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1481
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001482 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001483
1484 @retval QCBOR_ERR_NO_MORE_ITEMS
1485
1486 @retval QCBOR_ERR_BAD_BREAK
1487
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001488 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001489static QCBORError
1490QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001491{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001492 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001493 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001494
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 /*
1496 If out of bytes to consume, it is either the end of the top-level
1497 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001498
Laurence Lundblade642282a2020-06-23 12:00:33 -07001499 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1500 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1501 CBOR is exited, the length is set back to the top-level's length
1502 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001503 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001504 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001505 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001506 goto Done;
1507 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001508
Laurence Lundblade642282a2020-06-23 12:00:33 -07001509 /*
1510 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001511 array. The check for the end of an indefinite length array is
1512 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001513 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001514 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001515 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001516 goto Done;
1517 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001518
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001519 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001520 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001521 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1522 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001523 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001524 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301525
Laurence Lundblade642282a2020-06-23 12:00:33 -07001526 /*
1527 Breaks ending arrays/maps are always processed at the end of this
1528 function. They should never show up here.
1529 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301530 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001531 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301532 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301533 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001534
Laurence Lundblade642282a2020-06-23 12:00:33 -07001535 /*
1536 Record the nesting level for this data item before processing any
1537 of decrementing and descending.
1538 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001539 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundblade642282a2020-06-23 12:00:33 -07001541
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001542 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001543 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001544 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001545 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001546
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001547 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001548 of in the next chunk of code.
1549
1550 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001551 encloses them so a decrement needs to be done for them too, but
1552 that is done only when all the items in them have been
1553 processed, not when they are opened with the exception of an
1554 empty map or array.
1555 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001556 QCBORError uDescendErr;
1557 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001558 pDecodedItem->uDataType,
1559 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001560 if(uDescendErr != QCBOR_SUCCESS) {
1561 /* This error is probably a traversal error and it
1562 overrides the non-traversal error. */
1563 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001564 goto Done;
1565 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001566 }
1567
Laurence Lundblade02625d42020-06-25 14:41:41 -07001568 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1569 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1570 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001571 /*
1572 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001573 - A non-aggregate like an integer or string
1574 - An empty definite length map or array
1575 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001576
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001577 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001578 definite length map/array and break detection for an indefinite
1579 length map/array. If the end of the map/array was reached, then
1580 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001581 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001582 QCBORError uAscendErr;
1583 uAscendErr = NestLevelAscender(me, true);
1584 if(uAscendErr != QCBOR_SUCCESS) {
1585 /* This error is probably a traversal error and it
1586 overrides the non-traversal error. */
1587 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001588 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001589 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301590 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001592 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001593 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001594 Tell the caller what level is next. This tells them what
1595 maps/arrays were closed out and makes it possible for them to
1596 reconstruct the tree with just the information returned in
1597 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001598 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001599 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001600 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001601 pDecodedItem->uNextNestLevel = 0;
1602 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001603 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001604 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001606Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001607 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001608}
1609
Laurence Lundblade9b334962020-08-27 10:55:53 -07001610static void ShiftTags(QCBORItem *pDecodedItem)
1611{
1612 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1613 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1614 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1615 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1616}
1617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001618
Laurence Lundblade59289e52019-12-30 13:44:37 -08001619/*
1620 Mostly just assign the right data type for the date string.
1621 */
1622inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1623{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001624 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1625 return QCBOR_ERR_BAD_OPT_TAG;
1626 }
1627
1628 const UsefulBufC Temp = pDecodedItem->val.string;
1629 pDecodedItem->val.dateString = Temp;
1630 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001631 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001632 return QCBOR_SUCCESS;
1633}
1634
1635
Laurence Lundblade9b334962020-08-27 10:55:53 -07001636
Laurence Lundblade59289e52019-12-30 13:44:37 -08001637/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001638 The epoch formatted date. Turns lots of different forms of encoding
1639 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001640 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001641static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001642{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001643 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001644
1645 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1646
1647 switch (pDecodedItem->uDataType) {
1648
1649 case QCBOR_TYPE_INT64:
1650 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1651 break;
1652
1653 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001654 // This only happens for CBOR type 0 > INT64_MAX so it is
1655 // always an overflow.
1656 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1657 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001658 break;
1659
1660 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001661 case QCBOR_TYPE_FLOAT:
1662#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001663 {
1664 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001665 // conversion to an int64_t to be able to detect doubles that
1666 // are too large to fit into an int64_t. A double has 52
1667 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1668 // to a double actually causes a round up which is bad and
1669 // wrong for the comparison because it will allow conversion
1670 // of doubles that can't fit into a uint64_t. To remedy this
1671 // INT64_MAX - 0x7ff is used as the cutoff point because if
1672 // that value rounds up in conversion to double it will still
1673 // be less than INT64_MAX. 0x7ff is picked because it has 11
1674 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001676 // INT64_MAX seconds is on the order of 10 billion years, and
1677 // the earth is less than 5 billion years old, so for most
1678 // uses this conversion error won't occur even though doubles
1679 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680 //
1681 // Without the 0x7ff there is a ~30 minute range of time
1682 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001683 // where this code would go wrong. Some compilers
1684 // will generate warnings or errors without the 0x7ff
1685 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001686 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1687 pDecodedItem->val.dfnum :
1688 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001689 if(isnan(d) ||
1690 d > (double)(INT64_MAX - 0x7ff) ||
1691 d < (double)(INT64_MIN + 0x7ff)) {
1692 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001693 goto Done;
1694 }
1695 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001696 pDecodedItem->val.epochDate.fSecondsFraction =
1697 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001698 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001699#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001700
Laurence Lundbladec7114722020-08-13 05:11:40 -07001701 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001702 goto Done;
1703
Laurence Lundblade9682a532020-06-06 18:33:04 -07001704#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001705 break;
1706
1707 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001708 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 goto Done;
1710 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001711
Laurence Lundblade59289e52019-12-30 13:44:37 -08001712 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1713
1714Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001715 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001716}
1717
1718
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001719/*
1720 Mostly just assign the right data type for the bignum.
1721 */
1722inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1723{
1724 // Stack Use: UsefulBuf 1 -- 16
1725 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1726 return QCBOR_ERR_BAD_OPT_TAG;
1727 }
1728 const UsefulBufC Temp = pDecodedItem->val.string;
1729 pDecodedItem->val.bigNum = Temp;
1730 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1731 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1732 : QCBOR_TYPE_NEGBIGNUM);
1733 return QCBOR_SUCCESS;
1734}
1735
1736
Laurence Lundblade59289e52019-12-30 13:44:37 -08001737#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1738/*
1739 Decode decimal fractions and big floats.
1740
1741 When called pDecodedItem must be the array that is tagged as a big
1742 float or decimal fraction, the array that has the two members, the
1743 exponent and mantissa.
1744
1745 This will fetch and decode the exponent and mantissa and put the
1746 result back into pDecodedItem.
1747 */
1748inline static QCBORError
1749QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1750{
1751 QCBORError nReturn;
1752
1753 // --- Make sure it is an array; track nesting level of members ---
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1755 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1756 goto Done;
1757 }
1758
1759 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001760 // definite length arrays, but not for indefnite. Instead remember
1761 // the nesting level the two integers must be at, which is one
1762 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001763 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1764
1765 // --- Is it a decimal fraction or a bigfloat? ---
1766 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1767 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1768
1769 // --- Get the exponent ---
1770 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001771 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 if(nReturn != QCBOR_SUCCESS) {
1773 goto Done;
1774 }
1775 if(exponentItem.uNestingLevel != nNestLevel) {
1776 // Array is empty or a map/array encountered when expecting an int
1777 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1778 goto Done;
1779 }
1780 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1781 // Data arriving as an unsigned int < INT64_MAX has been converted
1782 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1783 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1784 // will be too large for this to handle and thus an error that will
1785 // get handled in the next else.
1786 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1787 } else {
1788 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1789 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1790 goto Done;
1791 }
1792
1793 // --- Get the mantissa ---
1794 QCBORItem mantissaItem;
1795 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1796 if(nReturn != QCBOR_SUCCESS) {
1797 goto Done;
1798 }
1799 if(mantissaItem.uNestingLevel != nNestLevel) {
1800 // Mantissa missing or map/array encountered when expecting number
1801 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1802 goto Done;
1803 }
1804 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1805 // Data arriving as an unsigned int < INT64_MAX has been converted
1806 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1807 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1808 // will be too large for this to handle and thus an error that
1809 // will get handled in an else below.
1810 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1811 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1812 // Got a good big num mantissa
1813 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1814 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001815 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1816 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1817 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001818 } else {
1819 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1820 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1821 goto Done;
1822 }
1823
1824 // --- Check that array only has the two numbers ---
1825 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001826 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001827 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1828 goto Done;
1829 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001830 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001831
1832Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833 return nReturn;
1834}
1835#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1836
1837
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001838inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1839{
1840 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1841 return QCBOR_ERR_BAD_OPT_TAG;
1842 }
1843 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1844 return QCBOR_SUCCESS;
1845}
1846
1847
1848inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1849{
1850 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1851 return QCBOR_ERR_BAD_OPT_TAG;
1852 }
1853 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001854
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001855 return QCBOR_SUCCESS;
1856}
1857
1858
1859inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1860{
1861 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1862 return QCBOR_ERR_BAD_OPT_TAG;
1863 }
1864 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001865
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001866 return QCBOR_SUCCESS;
1867}
1868
1869
1870inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1871{
1872 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1873 return QCBOR_ERR_BAD_OPT_TAG;
1874 }
1875 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001876
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001877 return QCBOR_SUCCESS;
1878}
1879
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001880
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001881inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1882{
1883 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1884 return QCBOR_ERR_BAD_OPT_TAG;
1885 }
1886 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001887
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001888 return QCBOR_SUCCESS;
1889}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001890
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001891
1892inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1893{
1894 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1895 return QCBOR_ERR_BAD_OPT_TAG;
1896 }
1897 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001898
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001899 return QCBOR_SUCCESS;
1900}
1901
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001902
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001903inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1904{
1905 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1906 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001907 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001908 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1909 } else {
1910 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001911
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001912 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001913
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914 return QCBOR_SUCCESS;
1915}
1916
1917
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001918inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1919{
1920 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1921 return QCBOR_ERR_BAD_OPT_TAG;
1922 }
1923 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001924
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001925 return QCBOR_SUCCESS;
1926}
1927
1928
Laurence Lundblade59289e52019-12-30 13:44:37 -08001929/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001930 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001932static QCBORError
1933QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934{
1935 QCBORError nReturn;
1936
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001937 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001938 if(nReturn != QCBOR_SUCCESS) {
1939 goto Done;
1940 }
1941
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001942 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001943 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001944
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001945 // Many of the functions here only just map a CBOR tag to
1946 // a QCBOR_TYPE for a string and could probably be
1947 // implemented with less object code. This implementation
1948 // of string types takes about 120 bytes of object code
1949 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001950 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 nReturn = DecodeDateString(pDecodedItem);
1952 break;
1953
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001954 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 nReturn = DecodeDateEpoch(pDecodedItem);
1956 break;
1957
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001958 case CBOR_TAG_POS_BIGNUM:
1959 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 nReturn = DecodeBigNum(pDecodedItem);
1961 break;
1962
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001963 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1964 case CBOR_TAG_DECIMAL_FRACTION:
1965 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966 // For aggregate tagged types, what goes into pTags is only collected
1967 // from the surrounding data item, not the contents, so pTags is not
1968 // passed on here.
1969
1970 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1971 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001972 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001973
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001974 case CBOR_TAG_CBOR:
1975 nReturn = DecodeWrappedCBOR(pDecodedItem);
1976 break;
1977
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001978 case CBOR_TAG_CBOR_SEQUENCE:
1979 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1980 break;
1981
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001982 case CBOR_TAG_URI:
1983 nReturn = DecodeURI(pDecodedItem);
1984 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001985
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001986 case CBOR_TAG_B64URL:
1987 nReturn = DecodeB64URL(pDecodedItem);
1988 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001989
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001990 case CBOR_TAG_B64:
1991 nReturn = DecodeB64(pDecodedItem);
1992 break;
1993
1994 case CBOR_TAG_MIME:
1995 case CBOR_TAG_BINARY_MIME:
1996 nReturn = DecodeMIME(pDecodedItem);
1997 break;
1998
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001999 case CBOR_TAG_REGEX:
2000 nReturn = DecodeRegex(pDecodedItem);
2001 break;
2002
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002003 case CBOR_TAG_BIN_UUID:
2004 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002005 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002006
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002007 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002008 // The end of the tag list or no tags
2009 // Successful exit from the loop.
2010 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002011
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002012 default:
2013 // A tag that is not understood
2014 // A successful exit from the loop
2015 goto Done;
2016
2017 }
2018 if(nReturn != QCBOR_SUCCESS) {
2019 goto Done;
2020 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002021 // A tag was successfully processed, shift it
2022 // out of the list of tags returned.
2023 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024 }
2025
2026Done:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002027 return nReturn;
2028}
2029
2030
2031QCBORError
2032QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2033{
2034 QCBORError uErr;
2035 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2036 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002037 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2038 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2039 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002040 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002041}
2042
2043
2044/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002045 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002046 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002047void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2048{
2049 if(pMe->uLastError != QCBOR_SUCCESS) {
2050 return;
2051 }
2052
2053 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2054}
2055
2056
2057/*
2058 Public function, see header qcbor/qcbor_decode.h file
2059 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002060QCBORError
2061QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2062 QCBORItem *pDecodedItem,
2063 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002064{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002065 QCBORError nReturn;
2066
2067 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2068 if(nReturn != QCBOR_SUCCESS) {
2069 return nReturn;
2070 }
2071
2072 if(pTags != NULL) {
2073 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002074 // Reverse the order because pTags is reverse of
2075 // QCBORItem.uTags.
2076 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002077 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002078 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002079 }
2080 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2081 return QCBOR_ERR_TOO_MANY_TAGS;
2082 }
2083 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2084 pTags->uNumUsed++;
2085 }
2086 }
2087
2088 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002089}
2090
2091
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002092/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302093 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302094 next one down. If a layer has no work to do for a particular item
2095 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002096
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2098 tagged data items, turning them into the local C representation.
2099 For the most simple it is just associating a QCBOR_TYPE with the data. For
2100 the complex ones that an aggregate of data items, there is some further
2101 decoding and a little bit of recursion.
2102
2103 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302104 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302105 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002106 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002107
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302108 - GetNext_MapEntry -- This handles the combining of two
2109 items, the label and the data, that make up a map entry.
2110 It only does work on maps. It combines the label and data
2111 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002112
Laurence Lundblade59289e52019-12-30 13:44:37 -08002113 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2114 tags into bit flags associated with the data item. No actual decoding
2115 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002116
Laurence Lundblade59289e52019-12-30 13:44:37 -08002117 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302118 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302119 string allocater to create contiguous space for the item. It
2120 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002121
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2123 atomic data item has a "major type", an integer "argument" and optionally
2124 some content. For text and byte strings, the content is the bytes
2125 that make up the string. These are the smallest data items that are
2126 considered to be well-formed. The content may also be other data items in
2127 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002128
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002129 Roughly this takes 300 bytes of stack for vars. Need to
2130 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002131
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302132 */
2133
2134
2135/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002136 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002137 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002138bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002139 const QCBORItem *pItem,
2140 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002141{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002142 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002143 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002144 break;
2145 }
2146 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002147 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002148 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002149 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002150
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002151 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002152}
2153
2154
2155/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002156 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002157 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002158QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002159{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002160 QCBORError uReturn = me->uLastError;
2161
2162 if(uReturn != QCBOR_SUCCESS) {
2163 goto Done;
2164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002165
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002166 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002167 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002168 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002169 goto Done;
2170 }
2171
2172 // Error out if not all the bytes are consumed
2173 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002174 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002175 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002176
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002177Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302178 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002179 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002180 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002181
Laurence Lundblade085d7952020-07-24 10:26:30 -07002182 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002183}
2184
2185
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002186/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002187 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002188*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002189// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002190uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2191 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002192 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002193{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002194 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2195 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002196 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002197 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002198 }
2199}
2200
Laurence Lundblade9b334962020-08-27 10:55:53 -07002201/*
2202 Public function, see header qcbor/qcbor_decode.h file
2203*/
2204uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2205 uint32_t uIndex)
2206{
2207 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2208 return CBOR_TAG_INVALID64;
2209 } else {
2210 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2211 }
2212}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002213
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002214/*
2215
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002216Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002217
Laurence Lundbladeee851742020-01-08 08:37:05 -08002218 - Hit end of input before it was expected while decoding type and
2219 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002220
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002221 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundbladeee851742020-01-08 08:37:05 -08002223 - Hit end of input while decoding a text or byte string
2224 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002225
Laurence Lundbladeee851742020-01-08 08:37:05 -08002226 - Encountered conflicting tags -- e.g., an item is tagged both a date
2227 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002228
Laurence Lundbladeee851742020-01-08 08:37:05 -08002229 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002230 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002231
Laurence Lundbladeee851742020-01-08 08:37:05 -08002232 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002233 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002234
Laurence Lundbladeee851742020-01-08 08:37:05 -08002235 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2236 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002237
Laurence Lundbladeee851742020-01-08 08:37:05 -08002238 - The type of a map label is not a string or int
2239 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002240
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002241 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002243 */
2244
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002245
2246
Laurence Lundbladef6531662018-12-04 10:42:22 +09002247
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002248/* ===========================================================================
2249 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002250
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002251 This implements a simple sting allocator for indefinite length
2252 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2253 implements the function type QCBORStringAllocate and allows easy
2254 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002255
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002256 This particular allocator is built-in for convenience. The caller
2257 can implement their own. All of this following code will get
2258 dead-stripped if QCBORDecode_SetMemPool() is not called.
2259
2260 This is a very primitive memory allocator. It does not track
2261 individual allocations, only a high-water mark. A free or
2262 reallocation must be of the last chunk allocated.
2263
2264 The size of the pool and offset to free memory are packed into the
2265 first 8 bytes of the memory pool so we don't have to keep them in
2266 the decode context. Since the address of the pool may not be
2267 aligned, they have to be packed and unpacked as if they were
2268 serialized data of the wire or such.
2269
2270 The sizes packed in are uint32_t to be the same on all CPU types
2271 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002272 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002273
2274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275static inline int
2276MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002277{
2278 // Use of UsefulInputBuf is overkill, but it is convenient.
2279 UsefulInputBuf UIB;
2280
Laurence Lundbladeee851742020-01-08 08:37:05 -08002281 // Just assume the size here. It was checked during SetUp so
2282 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002283 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2284 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2285 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2286 return UsefulInputBuf_GetError(&UIB);
2287}
2288
2289
Laurence Lundbladeee851742020-01-08 08:37:05 -08002290static inline int
2291MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002292{
2293 // Use of UsefulOutBuf is overkill, but convenient. The
2294 // length check performed here is useful.
2295 UsefulOutBuf UOB;
2296
2297 UsefulOutBuf_Init(&UOB, Pool);
2298 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2299 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2300 return UsefulOutBuf_GetError(&UOB);
2301}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002302
2303
2304/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002305 Internal function for an allocation, reallocation free and destuct.
2306
2307 Having only one function rather than one each per mode saves space in
2308 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002309
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002310 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2311 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002312static UsefulBuf
2313MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002314{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002315 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002316
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002317 uint32_t uPoolSize;
2318 uint32_t uFreeOffset;
2319
2320 if(uNewSize > UINT32_MAX) {
2321 // This allocator is only good up to 4GB. This check should
2322 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2323 goto Done;
2324 }
2325 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2326
2327 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2328 goto Done;
2329 }
2330
2331 if(uNewSize) {
2332 if(pMem) {
2333 // REALLOCATION MODE
2334 // Calculate pointer to the end of the memory pool. It is
2335 // assumed that pPool + uPoolSize won't wrap around by
2336 // assuming the caller won't pass a pool buffer in that is
2337 // not in legitimate memory space.
2338 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2339
2340 // Check that the pointer for reallocation is in the range of the
2341 // pool. This also makes sure that pointer math further down
2342 // doesn't wrap under or over.
2343 if(pMem >= pPool && pMem < pPoolEnd) {
2344 // Offset to start of chunk for reallocation. This won't
2345 // wrap under because of check that pMem >= pPool. Cast
2346 // is safe because the pool is always less than UINT32_MAX
2347 // because of check in QCBORDecode_SetMemPool().
2348 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2349
2350 // Check to see if the allocation will fit. uPoolSize -
2351 // uMemOffset will not wrap under because of check that
2352 // pMem is in the range of the uPoolSize by check above.
2353 if(uNewSize <= uPoolSize - uMemOffset) {
2354 ReturnValue.ptr = pMem;
2355 ReturnValue.len = uNewSize;
2356
2357 // Addition won't wrap around over because uNewSize was
2358 // checked to be sure it is less than the pool size.
2359 uFreeOffset = uMemOffset + uNewSize32;
2360 }
2361 }
2362 } else {
2363 // ALLOCATION MODE
2364 // uPoolSize - uFreeOffset will not underflow because this
2365 // pool implementation makes sure uFreeOffset is always
2366 // smaller than uPoolSize through this check here and
2367 // reallocation case.
2368 if(uNewSize <= uPoolSize - uFreeOffset) {
2369 ReturnValue.len = uNewSize;
2370 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002371 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002372 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002373 }
2374 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002375 if(pMem) {
2376 // FREE MODE
2377 // Cast is safe because of limit on pool size in
2378 // QCBORDecode_SetMemPool()
2379 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2380 } else {
2381 // DESTRUCT MODE
2382 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002383 }
2384 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002385
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002386 UsefulBuf Pool = {pPool, uPoolSize};
2387 MemPool_Pack(Pool, uFreeOffset);
2388
2389Done:
2390 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002391}
2392
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002393
Laurence Lundbladef6531662018-12-04 10:42:22 +09002394/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002395 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002396 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002397QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2398 UsefulBuf Pool,
2399 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002400{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002401 // The pool size and free mem offset are packed into the beginning
2402 // of the pool memory. This compile time check make sure the
2403 // constant in the header is correct. This check should optimize
2404 // down to nothing.
2405 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002406 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002407 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002408
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002409 // The pool size and free offset packed in to the beginning of pool
2410 // memory are only 32-bits. This check will optimize out on 32-bit
2411 // machines.
2412 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002413 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002414 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002415
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002416 // This checks that the pool buffer given is big enough.
2417 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002418 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002419 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002420
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002421 pMe->StringAllocator.pfAllocator = MemPool_Function;
2422 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2423 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002424
Laurence Lundblade30816f22018-11-10 13:40:22 +07002425 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002426}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002427
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002428
2429
Laurence Lundblade9b334962020-08-27 10:55:53 -07002430static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2431{
2432 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2433}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002434
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002435
2436/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002437 Consume an entire map or array (and do next to
2438 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002439 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002440static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002441ConsumeItem(QCBORDecodeContext *pMe,
2442 const QCBORItem *pItemToConsume,
2443 uint_fast8_t *puNextNestLevel)
2444{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002445 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002446 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002447
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002448 // If it is a map or array, this will tell if it is empty.
2449 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2450
2451 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2452 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002453
Laurence Lundblade1341c592020-04-11 14:19:05 -07002454 /* This works for definite and indefinite length
2455 * maps and arrays by using the nesting level
2456 */
2457 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002458 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002459 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002460 goto Done;
2461 }
2462 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002463
Laurence Lundblade1341c592020-04-11 14:19:05 -07002464 if(puNextNestLevel != NULL) {
2465 *puNextNestLevel = Item.uNextNestLevel;
2466 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002467 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002468
Laurence Lundblade1341c592020-04-11 14:19:05 -07002469 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002470 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002471 if(puNextNestLevel != NULL) {
2472 /* Just pass the nesting level through */
2473 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2474 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002475 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002477
2478Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002479 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480}
2481
2482
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483/* Return true if the labels in Item1 and Item2 are the same.
2484 Works only for integer and string labels. Returns false
2485 for any other type. */
2486static inline bool
2487MatchLabel(QCBORItem Item1, QCBORItem Item2)
2488{
2489 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2490 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2491 return true;
2492 }
2493 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002495 return true;
2496 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002497 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002498 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2499 return true;
2500 }
2501 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2502 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2503 return true;
2504 }
2505 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002506
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 /* Other label types are never matched */
2508 return false;
2509}
2510
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002511
2512/*
2513 Returns true if Item1 and Item2 are the same type
2514 or if either are of QCBOR_TYPE_ANY.
2515 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516static inline bool
2517MatchType(QCBORItem Item1, QCBORItem Item2)
2518{
2519 if(Item1.uDataType == Item2.uDataType) {
2520 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002521 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002522 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002523 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002524 return true;
2525 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002526 return false;
2527}
2528
2529
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002530/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002531 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002532
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002533 @param[in] pMe The decode context to search.
2534 @param[in,out] pItemArray The items to search for and the items found.
2535 @param[out] puOffset Byte offset of last item matched.
2536 @param[in] pCBContext Context for the not-found item call back.
2537 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002538
2539 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2540
Laurence Lundblade9b334962020-08-27 10:55:53 -07002541 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2542 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2543 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002544
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002545 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002546
2547 @retval Also errors returned by QCBORDecode_GetNext().
2548
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002549 On input pItemArray contains a list of labels and data types
2550 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002551
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002552 On output the fully retrieved items are filled in with
2553 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002554
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002555 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002556 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002557// TODO: make this handle indefinite length strings, possibly with
2558// allocation only when returning the string.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002559static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002560MapSearch(QCBORDecodeContext *pMe,
2561 QCBORItem *pItemArray,
2562 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002563 void *pCBContext,
2564 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002565{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002566 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002567 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002568
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002569 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002570 uReturn = pMe->uLastError;
2571 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002572 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002573
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002574 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002575 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2576 /* QCBOR_TYPE_NONE as first item indicates just looking
2577 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002578 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2579 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002580 }
2581
Laurence Lundblade085d7952020-07-24 10:26:30 -07002582 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2583 // It is an empty bounded array or map
2584 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2585 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002586 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002587 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002588 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002589 // Nothing is ever found in an empty array or map. All items
2590 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002591 uReturn = QCBOR_SUCCESS;
2592 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002593 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002594 }
2595
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002596 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002597 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2598
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002599 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002600 UsefulInputBuf_Seek(&(pMe->InBuf),
2601 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002602
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002603 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002604 Loop over all the items in the map or array. Each item
2605 could be a map or array, but label matching is only at
2606 the main level. This handles definite and indefinite
2607 length maps and arrays. The only reason this is ever
2608 called on arrays is to find their end position.
2609
2610 This will always run over all items in order to do
2611 duplicate detection.
2612
2613 This will exit with failure if it encounters an
2614 unrecoverable error, but continue on for recoverable
2615 errors.
2616
2617 If a recoverable error occurs on a matched item, then
2618 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002619 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002620 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002621 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002622 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002623 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002624 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002625
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002626 /* Get the item */
2627 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002628 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2629 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002630 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002631 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002632 goto Done;
2633 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002634 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002635 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002636 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002637 goto Done;
2638 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002639
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002640 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002641 bool bMatched = false;
2642 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2643 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002644 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002645 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2646 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002647 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002648 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002649 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002650 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002651 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002652 goto Done;
2653 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002654
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002655 if(uResult != QCBOR_SUCCESS) {
2656 uReturn = uResult;
2657 goto Done;
2658 }
2659
Laurence Lundblade1341c592020-04-11 14:19:05 -07002660 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002661 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002662 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002663 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002664 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002665 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002666 bMatched = true;
2667 }
2668 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002669
2670
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002671 if(!bMatched && pfCallback != NULL) {
2672 /*
2673 Call the callback on unmatched labels.
2674 (It is tempting to do duplicate detection here, but that would
2675 require dynamic memory allocation because the number of labels
2676 that might be encountered is unbounded.)
2677 */
2678 uReturn = (*pfCallback)(pCBContext, &Item);
2679 if(uReturn != QCBOR_SUCCESS) {
2680 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002681 }
2682 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002683
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002684 /*
2685 Consume the item whether matched or not. This
2686 does the work of traversing maps and array and
2687 everything in them. In this loop only the
2688 items at the current nesting level are examined
2689 to match the labels.
2690 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002691 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002692 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693 goto Done;
2694 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002695
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002696 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002697
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002698 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002699
2700 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002701
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002702 // Check here makes sure that this won't accidentally be
2703 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002704 // QCBOR_MAX_DECODE_INPUT_SIZE.
2705 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2706 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2707 goto Done;
2708 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002709 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2710 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002711
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002712 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002713 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2714
2715 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002716 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002717 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002718 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002719 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2720 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 }
2722 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002723
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002724 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002725}
2726
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002727
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002728/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002729 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002731void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2732 int64_t nLabel,
2733 uint8_t uQcborType,
2734 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002735{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002736 if(pMe->uLastError != QCBOR_SUCCESS) {
2737 return;
2738 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002739
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002740 QCBORItem OneItemSeach[2];
2741 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2742 OneItemSeach[0].label.int64 = nLabel;
2743 OneItemSeach[0].uDataType = uQcborType;
2744 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002745
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002746 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002747
2748 *pItem = OneItemSeach[0];
2749
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002750 if(uReturn != QCBOR_SUCCESS) {
2751 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002752 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002753 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002754 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755 }
2756
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002757 Done:
2758 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759}
2760
2761
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002762/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002763 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002764*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002765void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2766 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002767 uint8_t uQcborType,
2768 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002769{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002770 if(pMe->uLastError != QCBOR_SUCCESS) {
2771 return;
2772 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002774 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002775 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2776 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2777 OneItemSeach[0].uDataType = uQcborType;
2778 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002779
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002780 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2781 if(uReturn != QCBOR_SUCCESS) {
2782 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002783 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002784 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002785 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002786 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787 }
2788
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002789 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002790
2791Done:
2792 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002793}
2794
2795
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002796
Laurence Lundblade9b334962020-08-27 10:55:53 -07002797static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002798{
2799 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2800 if(uDataType == puTypeList[i]) {
2801 return QCBOR_SUCCESS;
2802 }
2803 }
2804 return QCBOR_ERR_UNEXPECTED_TYPE;
2805}
2806
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002807
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002808/**
2809 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002810 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2813 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002814
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002815 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2816 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002817static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002818{
2819 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2820 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2821 /* There are tags that QCBOR couldn't process on this item and
2822 the caller has told us there should not be. */
2823 return QCBOR_ERR_UNEXPECTED_TYPE;
2824 }
2825
2826 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2827 const int nItemType = pItem->uDataType;
2828
2829 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2830 // Must match the tag and only the tag
2831 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2832 }
2833
2834 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2835 if(uReturn == QCBOR_SUCCESS) {
2836 return QCBOR_SUCCESS;
2837 }
2838
2839 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2840 /* Must match the content type and only the content type.
2841 There was no match just above so it is a fail. */
2842 return QCBOR_ERR_UNEXPECTED_TYPE;
2843 }
2844
2845 /* If here it can match either the tag or the content
2846 and it hasn't matched the content, so the end
2847 result is whether it matches the tag. This is
2848 also the case that the CBOR standard discourages. */
2849
2850 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2851}
2852
Laurence Lundblade9b334962020-08-27 10:55:53 -07002853
Laurence Lundblade9b334962020-08-27 10:55:53 -07002854
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002855// This could be semi-private if need be
2856static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002857void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2858 int64_t nLabel,
2859 TagSpecification TagSpec,
2860 QCBORItem *pItem)
2861{
2862 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2863 if(pMe->uLastError != QCBOR_SUCCESS) {
2864 return;
2865 }
2866
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002867 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002868}
2869
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002870
2871// This could be semi-private if need be
2872static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002873void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2874 const char *szLabel,
2875 TagSpecification TagSpec,
2876 QCBORItem *pItem)
2877{
2878 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2879 if(pMe->uLastError != QCBOR_SUCCESS) {
2880 return;
2881 }
2882
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002883 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002884}
2885
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002886// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002887void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2888 int64_t nLabel,
2889 TagSpecification TagSpec,
2890 UsefulBufC *pString)
2891{
2892 QCBORItem Item;
2893 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2894 if(pMe->uLastError == QCBOR_SUCCESS) {
2895 *pString = Item.val.string;
2896 }
2897}
2898
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002899// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002900void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2901 const char * szLabel,
2902 TagSpecification TagSpec,
2903 UsefulBufC *pString)
2904{
2905 QCBORItem Item;
2906 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2907 if(pMe->uLastError == QCBOR_SUCCESS) {
2908 *pString = Item.val.string;
2909 }
2910}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002911
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002912/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002913 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002914*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002915void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002916{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002917 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2918 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002919}
2920
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002921/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002922 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002923*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002924void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2925 QCBORItem *pItemList,
2926 void *pCallbackCtx,
2927 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002928{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002929 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2930 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002931}
2932
2933
Laurence Lundblade34691b92020-05-18 22:25:25 -07002934static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002935{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002936 // The first item in pSearch is the one that is to be
2937 // entered. It should be the only one filled in. Any other
2938 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002939 if(pMe->uLastError != QCBOR_SUCCESS) {
2940 // Already in error state; do nothing.
2941 return;
2942 }
2943
2944 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002945 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002946 if(pMe->uLastError != QCBOR_SUCCESS) {
2947 return;
2948 }
2949
Laurence Lundblade9b334962020-08-27 10:55:53 -07002950 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002951 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002952 return;
2953 }
2954
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002955 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002956 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002957
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002958 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002959 be at the right place.
2960
2961 The UsefulInBuf offset could be anywhere, so no assumption is
2962 made about it.
2963
2964 No assumption is made about the pre-order nesting level either.
2965
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002966 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002967 the map level that is being entered.
2968 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002969 /* Seek to the data item that is the map or array */
2970 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002971
2972 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002973
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002974 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002975}
2976
2977
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002978/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002979 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002980*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002981void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002982{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002983 QCBORItem OneItemSeach[2];
2984 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2985 OneItemSeach[0].label.int64 = nLabel;
2986 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2987 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002988
Laurence Lundblade9b334962020-08-27 10:55:53 -07002989 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002990 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002991}
2992
2993
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002994/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002995 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002996*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002997void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002998{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002999 QCBORItem OneItemSeach[2];
3000 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3001 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3002 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3003 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003004
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003005 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003006}
3007
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003008/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003009 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003010*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003011void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003012{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003013 QCBORItem OneItemSeach[2];
3014 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3015 OneItemSeach[0].label.int64 = nLabel;
3016 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3017 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003018
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003019 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003020}
3021
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003022/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003023 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003024*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003025void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3026{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003027 QCBORItem OneItemSeach[2];
3028 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3029 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3030 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3031 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003032
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003033 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003034}
3035
3036
Laurence Lundblade02625d42020-06-25 14:41:41 -07003037// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003038void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003039{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003040 QCBORError uErr;
3041
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003042 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003043 if(pMe->uLastError != QCBOR_SUCCESS) {
3044 // Already in error state; do nothing.
3045 return;
3046 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003047
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003048 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003049 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003050 uErr = QCBORDecode_GetNext(pMe, &Item);
3051 if(uErr != QCBOR_SUCCESS) {
3052 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003053 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003054 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003055 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3056 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003057 }
3058
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003059 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003060
3061
Laurence Lundbladef0499502020-08-01 11:55:57 -07003062 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003063 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003064 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3065 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003066 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003067 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3068 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003069 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3070 DecodeNesting_Descend(&(pMe->nesting), uType);
3071 }
3072
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003073 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003074
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003075 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3076 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003077
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003078Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003079 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003080}
3081
Laurence Lundblade02625d42020-06-25 14:41:41 -07003082
3083/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003084 This is the common work for exiting a level that is a bounded map, array or bstr
3085 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003086
3087 One chunk of work is to set up the pre-order traversal so it is at
3088 the item just after the bounded map, array or bstr that is being
3089 exited. This is somewhat complex.
3090
3091 The other work is to level-up the bounded mode to next higest bounded
3092 mode or the top level if there isn't one.
3093 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003094static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003095ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003096{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003097 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003098
Laurence Lundblade02625d42020-06-25 14:41:41 -07003099 /*
3100 First the pre-order-traversal byte offset is positioned to the
3101 item just after the bounded mode item that was just consumed.
3102 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003103 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3104
Laurence Lundblade02625d42020-06-25 14:41:41 -07003105 /*
3106 Next, set the current nesting level to one above the bounded level
3107 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003108
Laurence Lundblade02625d42020-06-25 14:41:41 -07003109 DecodeNesting_CheckBoundedType() is always called before this and
3110 makes sure pCurrentBounded is valid.
3111 */
3112 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3113
3114 /*
3115 This does the complex work of leveling up the pre-order traversal
3116 when the end of a map or array or another bounded level is
3117 reached. It may do nothing, or ascend all the way to the top
3118 level.
3119 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003120 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003121 if(uErr != QCBOR_SUCCESS) {
3122 goto Done;
3123 }
3124
Laurence Lundblade02625d42020-06-25 14:41:41 -07003125 /*
3126 This makes the next highest bounded level the current bounded
3127 level. If there is no next highest level, then no bounded mode is
3128 in effect.
3129 */
3130 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003131
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003132 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003133
3134Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003135 return uErr;
3136}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003137
Laurence Lundblade02625d42020-06-25 14:41:41 -07003138
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003139// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003140void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003141{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003142 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003143 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003144 return;
3145 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003148
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003149 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003150 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003151 goto Done;
3152 }
3153
Laurence Lundblade02625d42020-06-25 14:41:41 -07003154 /*
3155 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003156 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003157 from previous map search, then do a dummy search.
3158 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003159 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003160 QCBORItem Dummy;
3161 Dummy.uLabelType = QCBOR_TYPE_NONE;
3162 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3163 if(uErr != QCBOR_SUCCESS) {
3164 goto Done;
3165 }
3166 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003167
Laurence Lundblade02625d42020-06-25 14:41:41 -07003168 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003169
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003170Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003171 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003172}
3173
3174
Laurence Lundblade1341c592020-04-11 14:19:05 -07003175
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003176static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003177 const QCBORItem *pItem,
3178 uint8_t uTagRequirement,
3179 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003180{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003181 if(pBstr) {
3182 *pBstr = NULLUsefulBufC;
3183 }
3184
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003185 if(pMe->uLastError != QCBOR_SUCCESS) {
3186 // Already in error state; do nothing.
3187 return pMe->uLastError;
3188 }
3189
3190 QCBORError uError = QCBOR_SUCCESS;
3191
3192 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3193 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3194 goto Done;;
3195 }
3196
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003197 const TagSpecification TagSpec =
3198 {
3199 uTagRequirement,
3200 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3201 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3202 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003203
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003204 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003205 if(uError != QCBOR_SUCCESS) {
3206 goto Done;
3207 }
3208
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003209 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003210 // Reverse the decrement done by GetNext() for the bstr so the
3211 // increment in NestLevelAscender() called by ExitBoundedLevel()
3212 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003213 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003214 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003215
3216 if(pBstr) {
3217 *pBstr = pItem->val.string;
3218 }
3219
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003220 // This saves the current length of the UsefulInputBuf and then
3221 // narrows the UsefulInputBuf to start and length of the wrapped
3222 // CBOR that is being entered.
3223 //
3224 // This makes sure the length is less than
3225 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3226 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3227 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3228 // the casts safe. uEndOfBstr will always be less than
3229 // uPreviousLength because of the way UsefulInputBuf works so there
3230 // is no need to check it. There is also a range check in the
3231 // seek.
3232 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003233 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003234 // amount to much code.
3235 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3236 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003237 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003238 goto Done;
3239 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003240 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003241 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003242 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003243
Laurence Lundblade02625d42020-06-25 14:41:41 -07003244 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003245 (uint32_t)uPreviousLength,
3246 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003247Done:
3248 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003249}
3250
3251
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252/*
3253 Public function, see header qcbor/qcbor_decode.h file
3254 */
3255void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003256 uint8_t uTagRequirement,
3257 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003258{
3259 if(pMe->uLastError != QCBOR_SUCCESS) {
3260 // Already in error state; do nothing.
3261 return;
3262 }
3263
3264 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003265 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003266 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3267 if(pMe->uLastError != QCBOR_SUCCESS) {
3268 return;
3269 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003270
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003271 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003272 &Item,
3273 uTagRequirement,
3274 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003275}
3276
3277
Laurence Lundblade02625d42020-06-25 14:41:41 -07003278/*
3279 Public function, see header qcbor/qcbor_decode.h file
3280 */
3281void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003282 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003283 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003284 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003285{
3286 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003287 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003288
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003289 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003290}
3291
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003292
Laurence Lundblade02625d42020-06-25 14:41:41 -07003293/*
3294 Public function, see header qcbor/qcbor_decode.h file
3295 */
3296void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003297 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003298 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003299 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003300{
3301 QCBORItem Item;
3302 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3303
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003304 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003305}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003306
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003307
Laurence Lundblade02625d42020-06-25 14:41:41 -07003308/*
3309 Public function, see header qcbor/qcbor_decode.h file
3310 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003311void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003312{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003313 if(pMe->uLastError != QCBOR_SUCCESS) {
3314 // Already in error state; do nothing.
3315 return;
3316 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003317
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003318 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003319 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003320 return;
3321 }
3322
3323 /*
3324 Reset the length of the UsefulInputBuf to what it was before
3325 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003326 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003327 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003328 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003329
3330
Laurence Lundblade02625d42020-06-25 14:41:41 -07003331 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003332 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003333}
3334
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003335
Laurence Lundbladee6430642020-03-14 21:15:44 -07003336
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003337
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003338
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003339
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003340
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003341
Laurence Lundblade9b334962020-08-27 10:55:53 -07003342static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003343{
3344 switch(pItem->uDataType) {
3345 case QCBOR_TYPE_TRUE:
3346 *pBool = true;
3347 return QCBOR_SUCCESS;
3348 break;
3349
3350 case QCBOR_TYPE_FALSE:
3351 *pBool = false;
3352 return QCBOR_SUCCESS;
3353 break;
3354
3355 default:
3356 return QCBOR_ERR_UNEXPECTED_TYPE;
3357 break;
3358 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003359 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003360}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003361
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003362
Laurence Lundblade9b334962020-08-27 10:55:53 -07003363
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003364/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003365 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003366*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003367void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003368{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003369 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003370 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003371 return;
3372 }
3373
Laurence Lundbladec4537442020-04-14 18:53:22 -07003374 QCBORError nError;
3375 QCBORItem Item;
3376
3377 nError = QCBORDecode_GetNext(pMe, &Item);
3378 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003379 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003380 return;
3381 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003382 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003383}
3384
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003385
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003386/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003387 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003388*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003389void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003390{
3391 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003392 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003393
Laurence Lundblade9b334962020-08-27 10:55:53 -07003394 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003395}
3396
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003397
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003398/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003399 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003400*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003401void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3402{
3403 QCBORItem Item;
3404 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3405
Laurence Lundblade9b334962020-08-27 10:55:53 -07003406 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003407}
3408
3409
3410
Laurence Lundblade9b334962020-08-27 10:55:53 -07003411/*
3412 A number of methods decode CBOR that is associated with a
3413 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003414
Laurence Lundblade9b334962020-08-27 10:55:53 -07003415 The API of the method returns the
3416 data in a way specific to the
3417
3418 No tags at all.
3419
3420
3421 Require tag for the particular type for the method and no other.
3422
3423
3424 Either no tags at all or the particular type for the method and no other.
3425
3426 No tag for particular type; pass other tags along.
3427
3428 Require the tag for the particular type; pass other tags along
3429
3430 Any tagging is OK; consume the tag for the particular type if present,
3431 pass other tags along.
3432
3433
3434 1) REQUIRED
3435- 1 XXXX -- works
3436- T 1 XXX -- works, T is returned
3437
3438 if(tag is of interest) {
3439 process content
3440 return T if present
3441 }
3442
3443
3444 2) FORBIDDEN
3445 - XXX -- works
3446 - T XXX -- ???
3447
3448 if(tag is of interest) {
3449 error out since tag is forbidden
3450 } else {
3451 process contents
3452 return T
3453 }
3454
3455 3) OPTIONAL
3456 - XXX works
3457 - 1 XXX works
3458 - T XXX
3459 - T 1 XXX works, T is returned
3460
3461if (inner tag is of interest) {
3462 process content
3463 return tag T if present
3464 } else if (there is no tag) {
3465 process content
3466 } else {
3467 process content if possible
3468 return T
3469 }
3470
3471A field is type X
3472 - tag for type X is REQUIRED
3473 - tag for type X is FORBIDDEN
3474 - tag for type X is optional
3475 - Other tags are FORBIDDEN
3476 - Other tags are ALLOWED
3477
3478
3479
3480 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003481
3482static void ProcessEpochDate(QCBORDecodeContext *pMe,
3483 QCBORItem *pItem,
3484 uint8_t uTagRequirement,
3485 int64_t *pnTime)
3486{
3487 if(pMe->uLastError != QCBOR_SUCCESS) {
3488 // Already in error state, do nothing
3489 return;
3490 }
3491
3492 QCBORError uErr;
3493
3494 const TagSpecification TagSpec =
3495 {
3496 uTagRequirement,
3497 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3498 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3499 };
3500
Laurence Lundblade4b270642020-08-14 12:53:07 -07003501 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003502 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3503 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003504 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003505 if(uErr != QCBOR_SUCCESS) {
3506 goto Done;
3507 }
3508
3509 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3510 uErr = DecodeDateEpoch(pItem);
3511 if(uErr != QCBOR_SUCCESS) {
3512 goto Done;
3513 }
3514 }
3515
Laurence Lundblade9b334962020-08-27 10:55:53 -07003516 // Save the tags in the last item's tags in the decode context
3517 // for QCBORDecode_GetNthTagOfLast()
3518 CopyTags(pMe, pItem);
3519
Laurence Lundbladec7114722020-08-13 05:11:40 -07003520 *pnTime = pItem->val.epochDate.nSeconds;
3521
3522Done:
3523 pMe->uLastError = (uint8_t)uErr;
3524}
3525
3526
3527void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3528 uint8_t uTagRequirement,
3529 int64_t *pnTime)
3530{
3531 if(pMe->uLastError != QCBOR_SUCCESS) {
3532 // Already in error state, do nothing
3533 return;
3534 }
3535
3536 QCBORItem Item;
3537 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3538
3539 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3540}
3541
3542
3543void
3544QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3545 int64_t nLabel,
3546 uint8_t uTagRequirement,
3547 int64_t *pnTime)
3548{
3549 QCBORItem Item;
3550 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3551 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3552}
3553
3554
3555void
3556QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3557 const char *szLabel,
3558 uint8_t uTagRequirement,
3559 int64_t *pnTime)
3560{
3561 QCBORItem Item;
3562 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3563 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3564}
3565
3566
3567
3568
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003569void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3570 TagSpecification TagSpec,
3571 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003572{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003573 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003574 // Already in error state, do nothing
3575 return;
3576 }
3577
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003578 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003579 QCBORItem Item;
3580
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003581 uError = QCBORDecode_GetNext(pMe, &Item);
3582 if(uError != QCBOR_SUCCESS) {
3583 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003584 return;
3585 }
3586
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003587 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003588
3589 if(pMe->uLastError == QCBOR_SUCCESS) {
3590 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003591 } else {
3592 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003593 }
3594}
3595
Laurence Lundbladec4537442020-04-14 18:53:22 -07003596
3597
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003598
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003599static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003600 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003601 UsefulBufC *pValue,
3602 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003603{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003604 const TagSpecification TagSpec =
3605 {
3606 uTagRequirement,
3607 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3608 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3609 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003610
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003611 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003612 if(uErr != QCBOR_SUCCESS) {
3613 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003614 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003615
3616 *pValue = pItem->val.string;
3617
3618 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3619 *pbIsNegative = false;
3620 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3621 *pbIsNegative = true;
3622 }
3623
3624 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003625}
3626
3627
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003628/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003629 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003630 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003631void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3632 uint8_t uTagRequirement,
3633 UsefulBufC *pValue,
3634 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003635{
3636 if(pMe->uLastError != QCBOR_SUCCESS) {
3637 // Already in error state, do nothing
3638 return;
3639 }
3640
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003641 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003642 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3643 if(uError != QCBOR_SUCCESS) {
3644 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003645 return;
3646 }
3647
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003648 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003649}
3650
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003651
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003652/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003653 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003654*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003655void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3656 int64_t nLabel,
3657 uint8_t uTagRequirement,
3658 UsefulBufC *pValue,
3659 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003660{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003661 QCBORItem Item;
3662 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003663 if(pMe->uLastError != QCBOR_SUCCESS) {
3664 return;
3665 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003666
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003667 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003668}
3669
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003670
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003671/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003672 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003673*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003674void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3675 const char *szLabel,
3676 uint8_t uTagRequirement,
3677 UsefulBufC *pValue,
3678 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003679{
3680 QCBORItem Item;
3681 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003682 if(pMe->uLastError != QCBOR_SUCCESS) {
3683 return;
3684 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003685
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003686 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003687}
3688
3689
3690
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003691
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003692// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003693QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3694 const QCBORItem *pItem,
3695 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003696 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003697{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003698 const TagSpecification TagSpecText =
3699 {
3700 uTagRequirement,
3701 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3702 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3703 };
3704 const TagSpecification TagSpecBinary =
3705 {
3706 uTagRequirement,
3707 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3708 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3709 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003710
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003711 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003712
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003713 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003714 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003715 if(pbIsTag257 != NULL) {
3716 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003717 }
3718 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003719 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003720 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003721 if(pbIsTag257 != NULL) {
3722 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003723 }
3724 uReturn = QCBOR_SUCCESS;
3725
3726 } else {
3727 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3728 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003729
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003730 return uReturn;
3731}
3732
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003733// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3734
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003735
3736
3737
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003738#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003740typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003741
3742
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003743// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003744static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003745{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003746 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003747
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003748 if(uResult != 0) {
3749 /* This loop will run a maximum of 19 times because
3750 * UINT64_MAX < 10 ^^ 19. More than that will cause
3751 * exit with the overflow error
3752 */
3753 for(; nExponent > 0; nExponent--) {
3754 if(uResult > UINT64_MAX / 10) {
3755 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3756 }
3757 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003759
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003760 for(; nExponent < 0; nExponent++) {
3761 uResult = uResult / 10;
3762 if(uResult == 0) {
3763 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3764 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003766 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003767 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003768
3769 *puResult = uResult;
3770
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003771 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003772}
3773
3774
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003775// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003776static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003778 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003779
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003780 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003781
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003782 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003784 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003785 */
3786 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003787 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003788 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003789 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003790 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003791 nExponent--;
3792 }
3793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003794 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003795 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3797 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003798 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003800 }
3801
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003802 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003803
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804 return QCBOR_SUCCESS;
3805}
3806
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003807
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003808/*
3809 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3810 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003811static inline QCBORError ExponentiateNN(int64_t nMantissa,
3812 int64_t nExponent,
3813 int64_t *pnResult,
3814 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003815{
3816 uint64_t uResult;
3817
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003818 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003819 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003820 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3821
3822 // Do the exponentiation of the positive mantissa
3823 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3824 if(uReturn) {
3825 return uReturn;
3826 }
3827
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828
Laurence Lundblade983500d2020-05-14 11:49:34 -07003829 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3830 of INT64_MIN. This assumes two's compliment representation where
3831 INT64_MIN is one increment farther from 0 than INT64_MAX.
3832 Trying to write -INT64_MIN doesn't work to get this because the
3833 compiler tries to work with an int64_t which can't represent
3834 -INT64_MIN.
3835 */
3836 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3837
3838 // Error out if too large
3839 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3841 }
3842
3843 // Casts are safe because of checks above
3844 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3845
3846 return QCBOR_SUCCESS;
3847}
3848
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003849
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003850/*
3851 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3852 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003853static inline QCBORError ExponentitateNU(int64_t nMantissa,
3854 int64_t nExponent,
3855 uint64_t *puResult,
3856 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003857{
3858 if(nMantissa < 0) {
3859 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3860 }
3861
3862 // Cast to unsigned is OK because of check for negative
3863 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3864 // Exponentiation is straight forward
3865 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3866}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003867
3868
3869/*
3870 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3871 */
3872static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3873 int64_t nExponent,
3874 uint64_t *puResult,
3875 fExponentiator pfExp)
3876{
3877 return (*pfExp)(uMantissa, nExponent, puResult);
3878}
3879
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003880#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3881
3882
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003883
3884
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003885
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003886static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003887{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003888 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003889
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003890 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003891 const uint8_t *pByte = BigNum.ptr;
3892 size_t uLen = BigNum.len;
3893 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003894 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003895 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003896 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003897 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003898 }
3899
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003900 *pResult = uResult;
3901 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003902}
3903
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003904
Laurence Lundblade887add82020-05-17 05:50:34 -07003905static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003906{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003907 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003908}
3909
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003910
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003911static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003912{
3913 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003914 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3915 if(uError) {
3916 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917 }
3918 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3919 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003920 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003921}
3922
3923
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003924static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003925{
3926 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003927 /* The negative integer furthest from zero for a C int64_t is
3928 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3929 negative number in CBOR is computed as -n - 1 where n is the
3930 encoded integer, where n is what is in the variable BigNum. When
3931 converting BigNum to a uint64_t, the maximum value is thus
3932 INT64_MAX, so that when it -n - 1 is applied to it the result will
3933 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003934
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003935 -n - 1 <= INT64_MIN.
3936 -n - 1 <= -INT64_MAX - 1
3937 n <= INT64_MAX.
3938 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003939 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003940 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003941 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003942 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003943
3944 /// Now apply -n - 1. The cast is safe because
3945 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3946 // is the largest positive integer that an int64_t can
3947 // represent. */
3948 *pnResult = -(int64_t)uResult - 1;
3949
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003950 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003951}
3952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003953
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003954
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003955
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003956
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003957/*
3958Convert a integers and floats to an int64_t.
3959
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003960\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003961
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003962\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003963
3964\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3965
3966\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3967
3968*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003969static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003970{
3971 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003972 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003973 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003974#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003975 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003976 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3977 http://www.cplusplus.com/reference/cmath/llround/
3978 */
3979 // Not interested in FE_INEXACT
3980 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003981 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3982 *pnValue = llround(pItem->val.dfnum);
3983 } else {
3984 *pnValue = lroundf(pItem->val.fnum);
3985 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003986 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3987 // llround() shouldn't result in divide by zero, but catch
3988 // it here in case it unexpectedly does. Don't try to
3989 // distinguish between the various exceptions because it seems
3990 // they vary by CPU, compiler and OS.
3991 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003992 }
3993 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003994 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003995 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003996#else
3997 return QCBOR_ERR_HW_FLOAT_DISABLED;
3998#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999 break;
4000
4001 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004002 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004003 *pnValue = pItem->val.int64;
4004 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004005 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004006 }
4007 break;
4008
4009 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004011 if(pItem->val.uint64 < INT64_MAX) {
4012 *pnValue = pItem->val.int64;
4013 } else {
4014 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4015 }
4016 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004018 }
4019 break;
4020
4021 default:
4022 return QCBOR_ERR_UNEXPECTED_TYPE;
4023 }
4024 return QCBOR_SUCCESS;
4025}
4026
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004027
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004028void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004029 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004031 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004032{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004033 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004034 return;
4035 }
4036
Laurence Lundbladee6430642020-03-14 21:15:44 -07004037 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004038 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4039 if(uError) {
4040 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004041 return;
4042 }
4043
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004044 if(pItem) {
4045 *pItem = Item;
4046 }
4047
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004048 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004049}
4050
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004051
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004052void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4053 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 int64_t *pnValue,
4056 QCBORItem *pItem)
4057{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004058 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004059 if(pMe->uLastError != QCBOR_SUCCESS) {
4060 return;
4061 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004062
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004063 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004064}
4065
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004066
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004067void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4068 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004069 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004070 int64_t *pnValue,
4071 QCBORItem *pItem)
4072{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004073 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004074 if(pMe->uLastError != QCBOR_SUCCESS) {
4075 return;
4076 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004078 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004079}
4080
4081
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004082/*
4083 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004085 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004086
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004087 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004088
4089 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4090
4091 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4092
4093 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004094static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096 switch(pItem->uDataType) {
4097
4098 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004099 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004100 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004101 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004103 }
4104 break;
4105
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004106 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004108 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004109 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004110 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004111 }
4112 break;
4113
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004114#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4115 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004116 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004117 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004118 pItem->val.expAndMantissa.nExponent,
4119 pnValue,
4120 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004121 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123 }
4124 break;
4125
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004126 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004128 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004129 pItem->val.expAndMantissa.nExponent,
4130 pnValue,
4131 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004132 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004134 }
4135 break;
4136
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004137 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004138 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004139 int64_t nMantissa;
4140 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004141 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4142 if(uErr) {
4143 return uErr;
4144 }
4145 return ExponentiateNN(nMantissa,
4146 pItem->val.expAndMantissa.nExponent,
4147 pnValue,
4148 Exponentitate10);
4149 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004151 }
4152 break;
4153
4154 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004156 int64_t nMantissa;
4157 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4159 if(uErr) {
4160 return uErr;
4161 }
4162 return ExponentiateNN(nMantissa,
4163 pItem->val.expAndMantissa.nExponent,
4164 pnValue,
4165 Exponentitate10);
4166 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004167 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168 }
4169 break;
4170
4171 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004172 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004173 int64_t nMantissa;
4174 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004175 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4176 if(uErr) {
4177 return uErr;
4178 }
4179 return ExponentiateNN(nMantissa,
4180 pItem->val.expAndMantissa.nExponent,
4181 pnValue,
4182 Exponentitate2);
4183 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004184 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004185 }
4186 break;
4187
4188 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004189 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004190 int64_t nMantissa;
4191 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004192 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4193 if(uErr) {
4194 return uErr;
4195 }
4196 return ExponentiateNN(nMantissa,
4197 pItem->val.expAndMantissa.nExponent,
4198 pnValue,
4199 Exponentitate2);
4200 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004201 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004202 }
4203 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004204#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4205
Laurence Lundbladee6430642020-03-14 21:15:44 -07004206
Laurence Lundbladec4537442020-04-14 18:53:22 -07004207 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004208 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004209}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004210
4211
Laurence Lundbladec4537442020-04-14 18:53:22 -07004212/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004213 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004214 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004216{
4217 QCBORItem Item;
4218
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004219 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004220
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004221 if(pMe->uLastError == QCBOR_SUCCESS) {
4222 // The above conversion succeeded
4223 return;
4224 }
4225
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004226 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004227 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004228 return;
4229 }
4230
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004231 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004232}
4233
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004234
4235/*
4236Public function, see header qcbor/qcbor_decode.h file
4237*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004238void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4239 int64_t nLabel,
4240 uint32_t uConvertTypes,
4241 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004242{
4243 QCBORItem Item;
4244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246
4247 if(pMe->uLastError == QCBOR_SUCCESS) {
4248 // The above conversion succeeded
4249 return;
4250 }
4251
4252 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4253 // The above conversion failed in a way that code below can't correct
4254 return;
4255 }
4256
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004257 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004258}
4259
4260
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004261/*
4262Public function, see header qcbor/qcbor_decode.h file
4263*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004264void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4265 const char *szLabel,
4266 uint32_t uConvertTypes,
4267 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004268{
4269 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004270 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004271
4272 if(pMe->uLastError == QCBOR_SUCCESS) {
4273 // The above conversion succeeded
4274 return;
4275 }
4276
4277 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4278 // The above conversion failed in a way that code below can't correct
4279 return;
4280 }
4281
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004282 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004283}
4284
4285
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004286static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004287{
4288 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004289 case QCBOR_TYPE_DOUBLE:
4290 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004291#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004292 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004293 // Can't use llround here because it will not convert values
4294 // greater than INT64_MAX and less than UINT64_MAX that
4295 // need to be converted so it is more complicated.
4296 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4297 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4298 if(isnan(pItem->val.dfnum)) {
4299 return QCBOR_ERR_FLOAT_EXCEPTION;
4300 } else if(pItem->val.dfnum < 0) {
4301 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4302 } else {
4303 double dRounded = round(pItem->val.dfnum);
4304 // See discussion in DecodeDateEpoch() for
4305 // explanation of - 0x7ff
4306 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4307 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4308 }
4309 *puValue = (uint64_t)dRounded;
4310 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004311 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004312 if(isnan(pItem->val.fnum)) {
4313 return QCBOR_ERR_FLOAT_EXCEPTION;
4314 } else if(pItem->val.fnum < 0) {
4315 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4316 } else {
4317 float fRounded = roundf(pItem->val.fnum);
4318 // See discussion in DecodeDateEpoch() for
4319 // explanation of - 0x7ff
4320 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4321 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4322 }
4323 *puValue = (uint64_t)fRounded;
4324 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004325 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004326 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4327 // round() and roundf() shouldn't result in exceptions here, but
4328 // catch them to be robust and thorough. Don't try to
4329 // distinguish between the various exceptions because it seems
4330 // they vary by CPU, compiler and OS.
4331 return QCBOR_ERR_FLOAT_EXCEPTION;
4332 }
4333
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004334 } else {
4335 return QCBOR_ERR_UNEXPECTED_TYPE;
4336 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004337#else
4338 return QCBOR_ERR_HW_FLOAT_DISABLED;
4339#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004340 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004341
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004342 case QCBOR_TYPE_INT64:
4343 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4344 if(pItem->val.int64 >= 0) {
4345 *puValue = (uint64_t)pItem->val.int64;
4346 } else {
4347 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4348 }
4349 } else {
4350 return QCBOR_ERR_UNEXPECTED_TYPE;
4351 }
4352 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004353
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004354 case QCBOR_TYPE_UINT64:
4355 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4356 *puValue = pItem->val.uint64;
4357 } else {
4358 return QCBOR_ERR_UNEXPECTED_TYPE;
4359 }
4360 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004361
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004362 default:
4363 return QCBOR_ERR_UNEXPECTED_TYPE;
4364 }
4365
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004366 return QCBOR_SUCCESS;
4367}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004368
4369
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004370void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004371 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004373 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004374{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004375 if(pMe->uLastError != QCBOR_SUCCESS) {
4376 return;
4377 }
4378
Laurence Lundbladec4537442020-04-14 18:53:22 -07004379 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004380
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004381 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4382 if(uError) {
4383 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004384 return;
4385 }
4386
Laurence Lundbladea826c502020-05-10 21:07:00 -07004387 if(pItem) {
4388 *pItem = Item;
4389 }
4390
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004391 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004392}
4393
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004394
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004395void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004396 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004397 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004398 uint64_t *puValue,
4399 QCBORItem *pItem)
4400{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004401 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004402 if(pMe->uLastError != QCBOR_SUCCESS) {
4403 return;
4404 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407}
4408
4409
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004410void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004411 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004412 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413 uint64_t *puValue,
4414 QCBORItem *pItem)
4415{
4416 if(pMe->uLastError != QCBOR_SUCCESS) {
4417 return;
4418 }
4419
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004420 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004421 if(pMe->uLastError != QCBOR_SUCCESS) {
4422 return;
4423 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426}
4427
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004428
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004429/*
4430 Public function, see header qcbor/qcbor_decode.h file
4431*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004432static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004433{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434 switch(pItem->uDataType) {
4435
4436 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004437 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004438 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4439 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004440 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441 }
4442 break;
4443
4444 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004445 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004446 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4447 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004448 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 }
4450 break;
4451
4452#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4453
4454 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004456 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004457 pItem->val.expAndMantissa.nExponent,
4458 puValue,
4459 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 }
4463 break;
4464
4465 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4468 pItem->val.expAndMantissa.nExponent,
4469 puValue,
4470 Exponentitate2);
4471 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 }
4474 break;
4475
4476 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004477 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004478 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004479 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004480 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004481 if(uErr != QCBOR_SUCCESS) {
4482 return uErr;
4483 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004484 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004485 pItem->val.expAndMantissa.nExponent,
4486 puValue,
4487 Exponentitate10);
4488 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004489 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004490 }
4491 break;
4492
4493 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004494 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4496 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004497 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004498 }
4499 break;
4500
4501 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004502 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004503 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004504 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004505 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 if(uErr != QCBOR_SUCCESS) {
4507 return uErr;
4508 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004509 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004510 pItem->val.expAndMantissa.nExponent,
4511 puValue,
4512 Exponentitate2);
4513 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004514 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004515 }
4516 break;
4517
4518 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004519 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004520 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4521 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004522 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 }
4524 break;
4525#endif
4526 default:
4527 return QCBOR_ERR_UNEXPECTED_TYPE;
4528 }
4529}
4530
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004531
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004532/*
4533 Public function, see header qcbor/qcbor_decode.h file
4534*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004535void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004536{
4537 QCBORItem Item;
4538
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004539 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004540
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004541 if(pMe->uLastError == QCBOR_SUCCESS) {
4542 // The above conversion succeeded
4543 return;
4544 }
4545
4546 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4547 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004548 return;
4549 }
4550
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004551 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004552}
4553
Laurence Lundbladec4537442020-04-14 18:53:22 -07004554
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004555/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004556 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004558void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004559 int64_t nLabel,
4560 uint32_t uConvertTypes,
4561 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004562{
4563 QCBORItem Item;
4564
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004565 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004566
4567 if(pMe->uLastError == QCBOR_SUCCESS) {
4568 // The above conversion succeeded
4569 return;
4570 }
4571
4572 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4573 // The above conversion failed in a way that code below can't correct
4574 return;
4575 }
4576
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004577 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004578}
4579
4580
4581/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004582 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004584void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004585 const char *szLabel,
4586 uint32_t uConvertTypes,
4587 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588{
4589 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591
4592 if(pMe->uLastError == QCBOR_SUCCESS) {
4593 // The above conversion succeeded
4594 return;
4595 }
4596
4597 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4598 // The above conversion failed in a way that code below can't correct
4599 return;
4600 }
4601
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603}
4604
4605
Laurence Lundblade9b334962020-08-27 10:55:53 -07004606static QCBORError ConvertDouble(const QCBORItem *pItem,
4607 uint32_t uConvertTypes,
4608 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004609{
4610 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004611 case QCBOR_TYPE_FLOAT:
4612#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4613 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4614 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004615 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004616 *pdValue = (double)pItem->val.fnum;
4617 } else {
4618 return QCBOR_ERR_UNEXPECTED_TYPE;
4619 }
4620 }
4621#else
4622 return QCBOR_ERR_HW_FLOAT_DISABLED;
4623#endif
4624 break;
4625
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004626 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004627 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4628 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 *pdValue = pItem->val.dfnum;
4630 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004632 }
4633 }
4634 break;
4635
4636 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004637#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004638 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004639 // A simple cast seems to do the job with no worry of exceptions.
4640 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004641 *pdValue = (double)pItem->val.int64;
4642
4643 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004644 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004646#else
4647 return QCBOR_ERR_HW_FLOAT_DISABLED;
4648#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004649 break;
4650
4651 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004652#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004653 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004654 // A simple cast seems to do the job with no worry of exceptions.
4655 // There will be precision loss for some values.
4656 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004658 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004659 }
4660 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004661#else
4662 return QCBOR_ERR_HW_FLOAT_DISABLED;
4663#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004664
4665 default:
4666 return QCBOR_ERR_UNEXPECTED_TYPE;
4667 }
4668
4669 return QCBOR_SUCCESS;
4670}
4671
4672
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004673void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004676 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004677{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004678 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004679 return;
4680 }
4681
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004682 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004683
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004684 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004685 if(uError) {
4686 pMe->uLastError = (uint8_t)uError;
4687 return;
4688 }
4689
4690 if(pItem) {
4691 *pItem = Item;
4692 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004693
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004694 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004695}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004696
Laurence Lundbladec4537442020-04-14 18:53:22 -07004697
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004698void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4699 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701 double *pdValue,
4702 QCBORItem *pItem)
4703{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004704 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004705 if(pMe->uLastError != QCBOR_SUCCESS) {
4706 return;
4707 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004708
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004710}
4711
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004712
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004713void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4714 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004715 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004716 double *pdValue,
4717 QCBORItem *pItem)
4718{
4719 if(pMe->uLastError != QCBOR_SUCCESS) {
4720 return;
4721 }
4722
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004723 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004724 if(pMe->uLastError != QCBOR_SUCCESS) {
4725 return;
4726 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004728 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729}
4730
4731
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004732#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004733static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4734{
4735 double dResult;
4736
4737 dResult = 0.0;
4738 const uint8_t *pByte = BigNum.ptr;
4739 size_t uLen = BigNum.len;
4740 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004741 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004742 while(uLen--) {
4743 dResult = (dResult * 256.0) + (double)*pByte++;
4744 }
4745
4746 return dResult;
4747}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004748#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4749
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004750
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004751static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004752{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004753#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004754 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004755 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4756
4757 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004759
4760#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004762 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004763 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4765 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4766 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004767 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768 }
4769 break;
4770
4771 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004772 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004773 // Underflow gives 0, overflow gives infinity
4774 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4775 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
4779 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004780#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781
4782 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004783 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4785 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 }
4788 break;
4789
4790 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004792 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 }
4796 break;
4797
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004798#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004799 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4802 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4803 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 }
4806 break;
4807
4808 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004809 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4811 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4812 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004813 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814 }
4815 break;
4816
4817 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004818 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004819 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4820 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4821 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004822 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823 }
4824 break;
4825
4826 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004827 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004828 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4830 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 }
4833 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004834#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4835
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 default:
4837 return QCBOR_ERR_UNEXPECTED_TYPE;
4838 }
4839
4840 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004841
4842#else
4843 (void)pItem;
4844 (void)uConvertTypes;
4845 (void)pdValue;
4846 return QCBOR_ERR_HW_FLOAT_DISABLED;
4847#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4848
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849}
4850
4851
4852/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004853 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004855void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4856 uint32_t uConvertTypes,
4857 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858{
4859
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004860 QCBORItem Item;
4861
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004863
4864 if(pMe->uLastError == QCBOR_SUCCESS) {
4865 // The above conversion succeeded
4866 return;
4867 }
4868
4869 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4870 // The above conversion failed in a way that code below can't correct
4871 return;
4872 }
4873
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004874 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004875}
4876
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877
4878/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004879 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004881void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4882 int64_t nLabel,
4883 uint32_t uConvertTypes,
4884 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885{
4886 QCBORItem Item;
4887
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004888 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889
4890 if(pMe->uLastError == QCBOR_SUCCESS) {
4891 // The above conversion succeeded
4892 return;
4893 }
4894
4895 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4896 // The above conversion failed in a way that code below can't correct
4897 return;
4898 }
4899
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004900 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901}
4902
4903
4904/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004905 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004907void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4908 const char *szLabel,
4909 uint32_t uConvertTypes,
4910 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004911{
4912 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914
4915 if(pMe->uLastError == QCBOR_SUCCESS) {
4916 // The above conversion succeeded
4917 return;
4918 }
4919
4920 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4921 // The above conversion failed in a way that code below can't correct
4922 return;
4923 }
4924
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004927
4928
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004929
4930
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004931#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004932static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4933{
4934 while((uInt & 0xff00000000000000UL) == 0) {
4935 uInt = uInt << 8;
4936 };
4937
4938 UsefulOutBuf UOB;
4939
4940 UsefulOutBuf_Init(&UOB, Buffer);
4941
4942 while(uInt) {
4943 const uint64_t xx = uInt & 0xff00000000000000UL;
4944 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4945 uInt = uInt << 8;
4946 (void)xx;
4947 }
4948
4949 return UsefulOutBuf_OutUBuf(&UOB);
4950}
4951
4952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004953static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4954 TagSpecification TagSpec,
4955 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004956{
4957 QCBORError uErr;
4958 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004959 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004960 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004961 if(uErr != QCBOR_SUCCESS) {
4962 goto Done;
4963 }
4964
4965 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4966 break; // Successful exit. Moving on to finish decoding.
4967 }
4968
4969 // The item is an array, which means an undecoded
4970 // mantissa and exponent, so decode it. It will then
4971 // have a different type and exit the loop if.
4972 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4973 if(uErr != QCBOR_SUCCESS) {
4974 goto Done;
4975 }
4976
4977 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004978 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004979 }
4980Done:
4981 return uErr;
4982}
4983
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004984
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004985static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004986 TagSpecification TagSpec,
4987 QCBORItem *pItem,
4988 int64_t *pnMantissa,
4989 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004990{
4991 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004992
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004993 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004994 if(uErr != QCBOR_SUCCESS) {
4995 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004996 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004997
Laurence Lundblade9b334962020-08-27 10:55:53 -07004998 switch (pItem->uDataType) {
4999
5000 case QCBOR_TYPE_DECIMAL_FRACTION:
5001 case QCBOR_TYPE_BIGFLOAT:
5002 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5003 *pnExponent = pItem->val.expAndMantissa.nExponent;
5004 break;
5005
5006 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5007 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5008 *pnExponent = pItem->val.expAndMantissa.nExponent;
5009 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5010 break;
5011
5012 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5013 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5014 *pnExponent = pItem->val.expAndMantissa.nExponent;
5015 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5016 break;
5017
5018 default:
5019 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5020 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005021
5022 Done:
5023 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005024}
5025
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005026
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005027static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005028 TagSpecification TagSpec,
5029 QCBORItem *pItem,
5030 UsefulBuf BufferForMantissa,
5031 UsefulBufC *pMantissa,
5032 bool *pbIsNegative,
5033 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005034{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005035 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005036
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005037 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005038 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005039 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005040 }
5041
5042 uint64_t uMantissa;
5043
5044 switch (pItem->uDataType) {
5045
5046 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5049 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5050 *pbIsNegative = false;
5051 } else {
5052 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5053 *pbIsNegative = true;
5054 }
5055 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5056 *pnExponent = pItem->val.expAndMantissa.nExponent;
5057 break;
5058
5059 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005060 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061 *pnExponent = pItem->val.expAndMantissa.nExponent;
5062 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5063 *pbIsNegative = false;
5064 break;
5065
5066 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005067 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005068 *pnExponent = pItem->val.expAndMantissa.nExponent;
5069 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5070 *pbIsNegative = true;
5071 break;
5072
5073 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005074 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005076
5077Done:
5078 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005079}
5080
5081
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005082/*
5083 Public function, see header qcbor/qcbor_decode.h file
5084*/
5085void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5086 uint8_t uTagRequirement,
5087 int64_t *pnMantissa,
5088 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005089{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005090 if(pMe->uLastError != QCBOR_SUCCESS) {
5091 return;
5092 }
5093
5094 QCBORItem Item;
5095 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5096 if(uError) {
5097 pMe->uLastError = (uint8_t)uError;
5098 return;
5099 }
5100
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005101 const TagSpecification TagSpec =
5102 {
5103 uTagRequirement,
5104 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5105 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5106 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005107
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005108 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005109}
5110
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005111
5112/*
5113 Public function, see header qcbor/qcbor_decode.h file
5114*/
5115void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005116 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005117 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 int64_t *pnMantissa,
5119 int64_t *pnExponent)
5120{
5121 if(pMe->uLastError != QCBOR_SUCCESS) {
5122 return;
5123 }
5124
5125 QCBORItem Item;
5126 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5127
5128 const TagSpecification TagSpec =
5129 {
5130 uTagRequirement,
5131 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5132 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5133 };
5134
5135 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5136}
5137
5138
5139/*
5140 Public function, see header qcbor/qcbor_decode.h file
5141*/
5142void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005143 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005144 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005145 int64_t *pnMantissa,
5146 int64_t *pnExponent)
5147{
5148 if(pMe->uLastError != QCBOR_SUCCESS) {
5149 return;
5150 }
5151
5152 QCBORItem Item;
5153 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5154
5155 const TagSpecification TagSpec =
5156 {
5157 uTagRequirement,
5158 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5159 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5160 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005161
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005162 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5163}
5164
5165
5166/*
5167 Public function, see header qcbor/qcbor_decode.h file
5168*/
5169void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5170 uint8_t uTagRequirement,
5171 UsefulBuf MantissaBuffer,
5172 UsefulBufC *pMantissa,
5173 bool *pbMantissaIsNegative,
5174 int64_t *pnExponent)
5175{
5176 if(pMe->uLastError != QCBOR_SUCCESS) {
5177 return;
5178 }
5179
5180 QCBORItem Item;
5181 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5182 if(uError) {
5183 pMe->uLastError = (uint8_t)uError;
5184 return;
5185 }
5186
5187 const TagSpecification TagSpec =
5188 {
5189 uTagRequirement,
5190 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5191 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5192 };
5193
5194 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5195}
5196
5197
5198/*
5199 Public function, see header qcbor/qcbor_decode.h file
5200*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005201void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005202 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005203 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005204 UsefulBuf BufferForMantissa,
5205 UsefulBufC *pMantissa,
5206 bool *pbIsNegative,
5207 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005208{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005209 if(pMe->uLastError != QCBOR_SUCCESS) {
5210 return;
5211 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005212
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005213 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005214 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005215 if(pMe->uLastError != QCBOR_SUCCESS) {
5216 return;
5217 }
5218
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005219 const TagSpecification TagSpec =
5220 {
5221 uTagRequirement,
5222 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5223 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5224 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005225
5226 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005227}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005228
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005229
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230/*
5231 Public function, see header qcbor/qcbor_decode.h file
5232*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005233void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005234 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005235 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005236 UsefulBuf BufferForMantissa,
5237 UsefulBufC *pMantissa,
5238 bool *pbIsNegative,
5239 int64_t *pnExponent)
5240{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005241 if(pMe->uLastError != QCBOR_SUCCESS) {
5242 return;
5243 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005244
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005245 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005246 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5247 if(pMe->uLastError != QCBOR_SUCCESS) {
5248 return;
5249 }
5250
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005251 const TagSpecification TagSpec =
5252 {
5253 uTagRequirement,
5254 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5255 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5256 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005257
5258 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5259}
5260
5261
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005262/*
5263 Public function, see header qcbor/qcbor_decode.h file
5264*/
5265void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5266 uint8_t uTagRequirement,
5267 int64_t *pnMantissa,
5268 int64_t *pnExponent)
5269{
5270 if(pMe->uLastError != QCBOR_SUCCESS) {
5271 return;
5272 }
5273
5274 QCBORItem Item;
5275 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5276 if(uError) {
5277 pMe->uLastError = (uint8_t)uError;
5278 return;
5279 }
5280 const TagSpecification TagSpec =
5281 {
5282 uTagRequirement,
5283 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5284 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5285 };
5286
5287 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5288}
5289
5290
5291/*
5292 Public function, see header qcbor/qcbor_decode.h file
5293*/
5294void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005296 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005297 int64_t *pnMantissa,
5298 int64_t *pnExponent)
5299{
5300 if(pMe->uLastError != QCBOR_SUCCESS) {
5301 return;
5302 }
5303
5304 QCBORItem Item;
5305 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5306 if(pMe->uLastError != QCBOR_SUCCESS) {
5307 return;
5308 }
5309
5310 const TagSpecification TagSpec =
5311 {
5312 uTagRequirement,
5313 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5314 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5315 };
5316
5317 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5318}
5319
5320
5321/*
5322 Public function, see header qcbor/qcbor_decode.h file
5323*/
5324void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005325 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005326 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005327 int64_t *pnMantissa,
5328 int64_t *pnExponent)
5329{
5330 if(pMe->uLastError != QCBOR_SUCCESS) {
5331 return;
5332 }
5333
5334 QCBORItem Item;
5335 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
5340 const TagSpecification TagSpec =
5341 {
5342 uTagRequirement,
5343 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5344 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5345 };
5346
5347 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5348}
5349
5350
5351/*
5352 Public function, see header qcbor/qcbor_decode.h file
5353*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005354void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5355 uint8_t uTagRequirement,
5356 UsefulBuf MantissaBuffer,
5357 UsefulBufC *pMantissa,
5358 bool *pbMantissaIsNegative,
5359 int64_t *pnExponent)
5360{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005361 if(pMe->uLastError != QCBOR_SUCCESS) {
5362 return;
5363 }
5364
5365 QCBORItem Item;
5366 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5367 if(uError) {
5368 pMe->uLastError = (uint8_t)uError;
5369 return;
5370 }
5371
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 const TagSpecification TagSpec =
5373 {
5374 uTagRequirement,
5375 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5376 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5377 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005378
5379 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005380}
5381
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005382
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005383/*
5384 Public function, see header qcbor/qcbor_decode.h file
5385*/
5386void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005387 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005388 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005389 UsefulBuf BufferForMantissa,
5390 UsefulBufC *pMantissa,
5391 bool *pbIsNegative,
5392 int64_t *pnExponent)
5393{
5394 if(pMe->uLastError != QCBOR_SUCCESS) {
5395 return;
5396 }
5397
5398 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005399 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5400 if(pMe->uLastError != QCBOR_SUCCESS) {
5401 return;
5402 }
5403
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005404 const TagSpecification TagSpec =
5405 {
5406 uTagRequirement,
5407 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5408 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5409 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005410
5411 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5412}
5413
5414
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415/*
5416 Public function, see header qcbor/qcbor_decode.h file
5417*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005418void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005419 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005420 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005421 UsefulBuf BufferForMantissa,
5422 UsefulBufC *pMantissa,
5423 bool *pbIsNegative,
5424 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005425{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 if(pMe->uLastError != QCBOR_SUCCESS) {
5427 return;
5428 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005429
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005430 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005431 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5432 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005433 return;
5434 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005435
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 const TagSpecification TagSpec =
5437 {
5438 uTagRequirement,
5439 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5440 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5441 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005442
5443 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005444}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005445
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005446#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */