blob: 0a9906e7a6642a759c7c06f33b74c34e0f569784 [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 Lundbladea8edadb2020-06-27 22:35:37 -0700222 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
225 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700226 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700230 // Not at a 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 Lundbladea8edadb2020-06-27 22:35:37 -0700238 // All checks passed, got to the end of a map/array
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.
329 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700330 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700331 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700332 }
333
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700334 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700335
336 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700337
338 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700339}
340
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700341
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700342inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 uint8_t uQCBORType,
345 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348
349 if(uCount == 0) {
350 // Nothing to do for empty definite lenth arrays. They are just are
351 // effectively the same as an item that is not a map or array
352 goto Done;
353 // Empty indefinite length maps and arrays are handled elsewhere
354 }
355
356 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
358 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700359 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360 goto Done;
361 }
362
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700363 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
366 }
367
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700368 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700369 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
370 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700371
372 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373
374Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 return uError;;
376}
377
378
379static inline void
380DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
381{
382 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
383}
384
385
386static inline void
387DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
388{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700390 pNesting->pCurrentBounded--;
391 if(DecodeNesting_IsCurrentBounded(pNesting)) {
392 break;
393 }
394 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395}
396
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700397static inline void
398DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded;
401}
402
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700404inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700406 uint32_t uEndOffset,
407 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700411 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 goto Done;
414 }
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700417 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
418 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421 pNesting->pCurrentBounded = pNesting->pCurrent;
422
423Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 return uError;;
425}
426
Laurence Lundbladed0304932020-06-27 10:59:38 -0700427
428static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430{
431 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432}
433
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
Laurence Lundbladeee851742020-01-08 08:37:05 -0800435inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700436DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700437{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700439 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
440 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700441}
442
443
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700444inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700445DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700446{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700447 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700448 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700450}
451
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700452
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700454DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700455{
456 *pNesting = *pSave;
457}
458
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462{
463 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
464}
465
466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700468DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700469{
470 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
471}
472
473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700475
476const char *TypeStr(uint8_t type)
477{
478 switch(type) {
479 case QCBOR_TYPE_MAP: return " map";
480 case QCBOR_TYPE_ARRAY: return "array";
481 case QCBOR_TYPE_BYTE_STRING: return " bstr";
482 default: return " --- ";
483 }
484}
485
486static char buf[20]; // Not thread safe, but that is OK
487const char *CountString(uint16_t uCount, uint16_t uTotal)
488{
489 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
490 strcpy(buf, "indefinite");
491 } else {
492 sprintf(buf, "%d/%d", uCount, uTotal);
493 }
494 return buf;
495}
496
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700497
Laurence Lundblade02625d42020-06-25 14:41:41 -0700498void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700499{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700500#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700501 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700502 szName,
503 (uint32_t)pBuf->cursor,
504 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700505
506 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700507 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700508 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700509 break;
510 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700511
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700512 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700513 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700514 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700515 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700516
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700517 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700518 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700519 pNesting->pLevels[i].u.bs.uEndOfBstr,
520 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700521
522 } else {
523 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700524 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
525 pNesting->pLevels[i].u.ma.uCountTotal));
526 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
527 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700528 }
529 }
530
531 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700532 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700533 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700534#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700535}
536
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700537
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700538
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
541
542 The following four functions are pretty wrappers for invocation of
543 the string allocator supplied by the caller.
544
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547static inline void
548StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800549{
550 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
551}
552
Laurence Lundbladeee851742020-01-08 08:37:05 -0800553// StringAllocator_Reallocate called with pMem NULL is
554// equal to StringAllocator_Allocate()
555static inline UsefulBuf
556StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
557 void *pMem,
558 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800559{
560 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
561}
562
Laurence Lundbladeee851742020-01-08 08:37:05 -0800563static inline UsefulBuf
564StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800565{
566 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
567}
568
Laurence Lundbladeee851742020-01-08 08:37:05 -0800569static inline void
570StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800571{
572 if(pMe->pfAllocator) {
573 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
574 }
575}
576
577
578
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579/*===========================================================================
580 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700581
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800582 See qcbor/qcbor_decode.h for definition of the object
583 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800584 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585/*
586 Public function, see header file
587 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588void QCBORDecode_Init(QCBORDecodeContext *me,
589 UsefulBufC EncodedCBOR,
590 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591{
592 memset(me, 0, sizeof(QCBORDecodeContext));
593 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800594 // Don't bother with error check on decode mode. If a bad value is
595 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700596 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700597 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700598 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700599 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700600 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700601}
602
603
604/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700605 Public function, see header file
606 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800607void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
608 QCBORStringAllocate pfAllocateFunction,
609 void *pAllocateContext,
610 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700611{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
613 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
614 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700615}
616
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800617
618/*
619 Public function, see header file
620 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700621void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800622 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700623{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700624 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700625 (void)pMe;
626 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700627}
628
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700629
630/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800631 This decodes the fundamental part of a CBOR data item, the type and
632 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700634 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800635
Laurence Lundbladeee851742020-01-08 08:37:05 -0800636 This does the network->host byte order conversion. The conversion
637 here also results in the conversion for floats in addition to that
638 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800639
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700640 This returns:
641 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800642
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800644 tags and floats and length for strings and arrays
645
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800647 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800648
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649 The int type is preferred to uint8_t for some variables as this
650 avoids integer promotions, can reduce code size and makes
651 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700652
653 @retval QCBOR_ERR_UNSUPPORTED
654
655 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800657inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
658 int *pnMajorType,
659 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800660 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700661{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700662 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800663
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800665 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 const int nTmpMajorType = nInitialByte >> 5;
669 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800670
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800671 // Where the number or argument accumulates
672 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800673
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700675 // Need to get 1,2,4 or 8 additional argument bytes. Map
676 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800677 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800678
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800679 // Loop getting all the bytes in the argument
680 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800682 // This shift and add gives the endian conversion
683 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
684 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800685 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800686 // The reserved and thus-far unused additional info values
687 nReturn = QCBOR_ERR_UNSUPPORTED;
688 goto Done;
689 } else {
690 // Less than 24, additional info is argument or 31, an indefinite length
691 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800692 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695 if(UsefulInputBuf_GetError(pUInBuf)) {
696 nReturn = QCBOR_ERR_HIT_END;
697 goto Done;
698 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700 // All successful if we got here.
701 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800702 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800703 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800704 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800705
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700706Done:
707 return nReturn;
708}
709
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800710
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800712 CBOR doesn't explicitly specify two's compliment for integers but all
713 CPUs use it these days and the test vectors in the RFC are so. All
714 integers in the CBOR structure are positive and the major type
715 indicates positive or negative. CBOR can express positive integers
716 up to 2^x - 1 where x is the number of bits and negative integers
717 down to 2^x. Note that negative numbers can be one more away from
718 zero than positive. Stdint, as far as I can tell, uses two's
719 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundblade9b334962020-08-27 10:55:53 -0700721 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 used carefully here, and in particular why it isn't used in the interface.
723 Also see
724 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
725
726 Int is used for values that need less than 16-bits and would be subject
727 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700728
729 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800731inline static QCBORError
732DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700734 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
737 if (uNumber <= INT64_MAX) {
738 pDecodedItem->val.int64 = (int64_t)uNumber;
739 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800740
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741 } else {
742 pDecodedItem->val.uint64 = uNumber;
743 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745 }
746 } else {
747 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 // CBOR's representation of negative numbers lines up with the
749 // two-compliment representation. A negative integer has one
750 // more in range than a positive integer. INT64_MIN is
751 // equal to (-INT64_MAX) - 1.
752 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755 } else {
756 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000757 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700758 nReturn = QCBOR_ERR_INT_OVERFLOW;
759 }
760 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700762 return nReturn;
763}
764
765// Make sure #define value line up as DecodeSimple counts on this.
766#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
767#error QCBOR_TYPE_FALSE macro value wrong
768#endif
769
770#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
771#error QCBOR_TYPE_TRUE macro value wrong
772#endif
773
774#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
775#error QCBOR_TYPE_NULL macro value wrong
776#endif
777
778#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
779#error QCBOR_TYPE_UNDEF macro value wrong
780#endif
781
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700782#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
783#error QCBOR_TYPE_BREAK macro value wrong
784#endif
785
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700786#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
787#error QCBOR_TYPE_DOUBLE macro value wrong
788#endif
789
790#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
791#error QCBOR_TYPE_FLOAT macro value wrong
792#endif
793
794/*
795 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700796
797 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
798
799 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800802DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700804 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700806 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800807 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700808 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800811 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800812 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
813 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800814
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700815 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700816#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700817 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700818 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700819 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700820 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
821 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700822#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700823 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700824#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700825 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700826 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700827 // Single precision is normally returned as a double
828 // since double is widely supported, there is no loss of
829 // precision, it makes it easy for the caller in
830 // most cases and it can be converted back to single
831 // with no loss of precision
832 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700833 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700834 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700835 {
836 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
837#ifndef QCBOR_DISABLE_FLOAT_HW_USE
838 // In the normal case, use HW to convert float to double.
839 pDecodedItem->val.dfnum = (double)f;
840 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700841#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700842 // Use of float HW is disabled, return as a float.
843 pDecodedItem->val.fnum = f;
844 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
845
846 // IEEE754_FloatToDouble() could be used here to return
847 // as a double, but it adds object code and most likely
848 // anyone disabling FLOAT HW use doesn't care about
849 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700850#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700851 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700852 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700853
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700854 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700855 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700856 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700857 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700859 case CBOR_SIMPLEV_FALSE: // 20
860 case CBOR_SIMPLEV_TRUE: // 21
861 case CBOR_SIMPLEV_NULL: // 22
862 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700863 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700864 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700866 case CBOR_SIMPLEV_ONEBYTE: // 24
867 if(uNumber <= CBOR_SIMPLE_BREAK) {
868 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700869 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 goto Done;
871 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800872 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800874
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875 default: // 0-19
876 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800877 /*
878 DecodeTypeAndNumber will make uNumber equal to
879 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
880 safe because the 2, 4 and 8 byte lengths of uNumber are in
881 the double/float cases above
882 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700883 pDecodedItem->val.uSimple = (uint8_t)uNumber;
884 break;
885 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887Done:
888 return nReturn;
889}
890
891
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700892/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530893 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700894
895 @retval QCBOR_ERR_HIT_END
896
897 @retval QCBOR_ERR_STRING_ALLOCATE
898
899 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800901inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
902 int nMajorType,
903 uint64_t uStrLen,
904 UsefulInputBuf *pUInBuf,
905 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700907 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800909 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
910 // This check makes the casts to size_t below safe.
911
912 // 4 bytes less than the largest sizeof() so this can be tested by
913 // putting a SIZE_MAX length in the CBOR test input (no one will
914 // care the limit on strings is 4 bytes shorter).
915 if(uStrLen > SIZE_MAX-4) {
916 nReturn = QCBOR_ERR_STRING_TOO_LONG;
917 goto Done;
918 }
919
920 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530921 if(UsefulBuf_IsNULLC(Bytes)) {
922 // Failed to get the bytes for this string item
923 nReturn = QCBOR_ERR_HIT_END;
924 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700925 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530926
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800927 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530928 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800929 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530930 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700931 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530932 goto Done;
933 }
934 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800935 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530936 } else {
937 // Normal case with no string allocator
938 pDecodedItem->val.string = Bytes;
939 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800940 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800941 // Cast because ternary operator causes promotion to integer
942 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
943 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530945Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700946 return nReturn;
947}
948
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700951
952
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953
954
Laurence Lundbladeee851742020-01-08 08:37:05 -0800955// Make sure the constants align as this is assumed by
956// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
958#error QCBOR_TYPE_ARRAY value not lined up with major type
959#endif
960#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
961#error QCBOR_TYPE_MAP value not lined up with major type
962#endif
963
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 This gets a single data item and decodes it including preceding
966 optional tagging. This does not deal with arrays and maps and nesting
967 except to decode the data item introducing them. Arrays and maps are
968 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundbladeee851742020-01-08 08:37:05 -0800970 Errors detected here include: an array that is too long to decode,
971 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700972
973 @retval QCBOR_ERR_UNSUPPORTED
974
975 @retval QCBOR_ERR_HIT_END
976
977 @retval QCBOR_ERR_INT_OVERFLOW
978
979 @retval QCBOR_ERR_STRING_ALLOCATE
980
981 @retval QCBOR_ERR_STRING_TOO_LONG
982
983 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
984
985 @retval QCBOR_ERR_BAD_TYPE_7
986
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700987 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800988static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
989 QCBORItem *pDecodedItem,
990 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700992 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800993
Laurence Lundbladeee851742020-01-08 08:37:05 -0800994 /*
995 Get the major type and the number. Number could be length of more
996 bytes or the value depending on the major type nAdditionalInfo is
997 an encoding of the length of the uNumber and is needed to decode
998 floats and doubles
999 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001002 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001004 memset(pDecodedItem, 0, sizeof(QCBORItem));
1005
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001006 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001007
Laurence Lundbladeee851742020-01-08 08:37:05 -08001008 // Error out here if we got into trouble on the type and number. The
1009 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001010 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001012 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladeee851742020-01-08 08:37:05 -08001014 // At this point the major type and the value are valid. We've got
1015 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001016 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1018 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001019 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001020 nReturn = QCBOR_ERR_BAD_INT;
1021 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001023 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001024 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1027 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001028 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1029 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
1030 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
1031 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +05301032 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001034 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 }
1036 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001037
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1039 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1040 // Record the number of items in the array or map
1041 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001042 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001043 goto Done;
1044 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001045 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001046 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001048 // type conversion OK because of check above
1049 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001051 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001052 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1053 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001056 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001057 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001058 nReturn = QCBOR_ERR_BAD_INT;
1059 } else {
1060 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001061 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001062 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundbladeee851742020-01-08 08:37:05 -08001065 case CBOR_MAJOR_TYPE_SIMPLE:
1066 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001067 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001069
Laurence Lundbladeee851742020-01-08 08:37:05 -08001070 default:
1071 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 nReturn = QCBOR_ERR_UNSUPPORTED;
1073 break;
1074 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001076Done:
1077 return nReturn;
1078}
1079
1080
1081
1082/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001083 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001084 individual chunk items together into one QCBORItem using the string
1085 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001088
1089 @retval QCBOR_ERR_UNSUPPORTED
1090
1091 @retval QCBOR_ERR_HIT_END
1092
1093 @retval QCBOR_ERR_INT_OVERFLOW
1094
1095 @retval QCBOR_ERR_STRING_ALLOCATE
1096
1097 @retval QCBOR_ERR_STRING_TOO_LONG
1098
1099 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1100
1101 @retval QCBOR_ERR_BAD_TYPE_7
1102
1103 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1104
1105 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001107static inline QCBORError
1108GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001109{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001110 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001111
1112 // Get pointer to string allocator. First use is to pass it to
1113 // GetNext_Item() when option is set to allocate for *every* string.
1114 // Second use here is to allocate space to coallese indefinite
1115 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001116 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1117 &(me->StringAllocator) :
1118 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001119
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001120 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001121 nReturn = GetNext_Item(&(me->InBuf),
1122 pDecodedItem,
1123 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 if(nReturn) {
1125 goto Done;
1126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001128 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301129 // code in this function from here down can be eliminated. Run tests, except
1130 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001131
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001132 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001133 const uint8_t uStringType = pDecodedItem->uDataType;
1134 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135 goto Done; // no need to do any work here on non-string types
1136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001137
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001138 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301139 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001140 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001142
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301143 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001144 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1146 goto Done;
1147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundblade4b270642020-08-14 12:53:07 -07001149 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001150 UsefulBufC FullString = NULLUsefulBufC;
1151
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001152 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001153 // Get item for next chunk
1154 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001155 // NULL string allocator passed here. Do not need to allocate
1156 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001157 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001159 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001161
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301162 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001163 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001164 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001165 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301166 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001167 break;
1168 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001169
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001170 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301171 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001172 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001173 if(StringChunkItem.uDataType != uStringType ||
1174 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001175 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001176 break;
1177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301179 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001180 // The first time throurgh FullString.ptr is NULL and this is
1181 // equivalent to StringAllocator_Allocate()
1182 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1183 UNCONST_POINTER(FullString.ptr),
1184 FullString.len + StringChunkItem.val.string.len);
1185
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301187 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001188 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189 break;
1190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001192 // Copy new string chunk at the end of string so far.
1193 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001195
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001196 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1197 // Getting the item failed, clean up the allocated memory
1198 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001201Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001202 return nReturn;
1203}
1204
Laurence Lundblade9b334962020-08-27 10:55:53 -07001205static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001206 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208 } else if(uTagVal == CBOR_TAG_INVALID16) {
1209 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001210 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001211 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001212 return me->auMappedTags[x];
1213 }
1214}
1215
Laurence Lundblade9b334962020-08-27 10:55:53 -07001216
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001217/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001218 Gets all optional tag data items preceding a data item that is not an
1219 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001220
1221 @retval QCBOR_ERR_UNSUPPORTED
1222
1223 @retval QCBOR_ERR_HIT_END
1224
1225 @retval QCBOR_ERR_INT_OVERFLOW
1226
1227 @retval QCBOR_ERR_STRING_ALLOCATE
1228
1229 @retval QCBOR_ERR_STRING_TOO_LONG
1230
1231 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1232
1233 @retval QCBOR_ERR_BAD_TYPE_7
1234
1235 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1236
1237 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1238
1239 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001240 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001241static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001242GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001243{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001244 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1245 CBOR_TAG_INVALID16,
1246 CBOR_TAG_INVALID16,
1247 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001248
Laurence Lundblade9b334962020-08-27 10:55:53 -07001249 QCBORError uReturn = QCBOR_SUCCESS;
1250
Laurence Lundblade59289e52019-12-30 13:44:37 -08001251 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001252 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001253 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1254 if(uErr != QCBOR_SUCCESS) {
1255 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001256 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001258
Laurence Lundblade9b334962020-08-27 10:55:53 -07001259 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001260 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001261 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001262 break;
1263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001264
Laurence Lundblade9b334962020-08-27 10:55:53 -07001265 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1266 // No room in the tag list
1267 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1268 // Continue on to get all tags on this item even though
1269 // it is erroring out in the end. This is a resource limit
1270 // error, not an problem with being well-formed CBOR.
1271 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001272 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001273 // Slide tags over one in the array to make room at index 0
1274 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1275 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001277
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001279 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001280 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001281 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001283 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 break;
1285 }
1286 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1287 break;
1288 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001289 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001290 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1291 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001292 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1293 // Continue on to get all tags on this item even though
1294 // it is erroring out in the end. This is a resource limit
1295 // error, not an problem with being well-formed CBOR.
1296 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001297 }
1298
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001299 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001300 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001301 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302
1303 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001304 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001305 }
1306 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001307
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001308Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001309 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001310}
1311
1312
1313/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001314 This layer takes care of map entries. It combines the label and data
1315 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001316
1317 @retval QCBOR_ERR_UNSUPPORTED
1318
1319 @retval QCBOR_ERR_HIT_END
1320
1321 @retval QCBOR_ERR_INT_OVERFLOW
1322
1323 @retval QCBOR_ERR_STRING_ALLOCATE
1324
1325 @retval QCBOR_ERR_STRING_TOO_LONG
1326
1327 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1328
1329 @retval QCBOR_ERR_BAD_TYPE_7
1330
1331 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1332
1333 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1334
1335 @retval QCBOR_ERR_TOO_MANY_TAGS
1336
1337 @retval QCBOR_ERR_MAP_LABEL_TYPE
1338
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001339 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001340 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001341static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001342GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001343{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001344 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001345 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001346 if(nReturn)
1347 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001348
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001349 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001350 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001351 goto Done;
1352 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001353
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001354 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1355 // In a map and caller wants maps decoded, not treated as arrays
1356
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001357 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001358 // If in a map and the right decoding mode, get the label
1359
Laurence Lundbladeee851742020-01-08 08:37:05 -08001360 // Save label in pDecodedItem and get the next which will
1361 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001362 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001363 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001364 if(nReturn)
1365 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001366
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301367 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001368
1369 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1370 // strings are always good labels
1371 pDecodedItem->label.string = LabelItem.val.string;
1372 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1373 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001374 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001375 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1376 goto Done;
1377 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1378 pDecodedItem->label.int64 = LabelItem.val.int64;
1379 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1380 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1381 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1382 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1383 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1384 pDecodedItem->label.string = LabelItem.val.string;
1385 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1386 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1387 } else {
1388 // label is not an int or a string. It is an arrray
1389 // or a float or such and this implementation doesn't handle that.
1390 // Also, tags on labels are ignored.
1391 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1392 goto Done;
1393 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001394 }
1395 } else {
1396 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001397 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001398 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001399 goto Done;
1400 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001401 // Decoding a map as an array
1402 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001403 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1404 // Cast is needed because of integer promotion
1405 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001406 }
1407 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001408
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001409Done:
1410 return nReturn;
1411}
1412
1413
Laurence Lundblade02625d42020-06-25 14:41:41 -07001414/*
1415 See if next item is a CBOR break. If it is, it is consumed,
1416 if not it is not consumed.
1417*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001418static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001419NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1420{
1421 *pbNextIsBreak = false;
1422 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001423 QCBORItem Peek;
1424 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1425 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1426 if(uReturn != QCBOR_SUCCESS) {
1427 return uReturn;
1428 }
1429 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001430 // It is not a break, rewind so it can be processed normally.
1431 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001432 } else {
1433 *pbNextIsBreak = true;
1434 }
1435 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001436
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001437 return QCBOR_SUCCESS;
1438}
1439
1440
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001441/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001442 An item was just consumed, now figure out if it was the
1443 end of an array or map that can be closed out. That
1444 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001445*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001446static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001447{
1448 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001449
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450 /* This loops ascending nesting levels as long as there is ascending to do */
1451 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1452
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001453 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1456 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458 break;
1459 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001460 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001461
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001462 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001463 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001464 bool bIsBreak = false;
1465 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1466 if(uReturn != QCBOR_SUCCESS) {
1467 goto Done;
1468 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001469
1470 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001471 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001472 break;
1473 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001474
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001475 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001476 /*
1477 Break occurred inside a bstr-wrapped CBOR or
1478 in the top level sequence. This is always an
1479 error because neither are an indefinte length
1480 map/array.
1481 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001482 uReturn = QCBOR_ERR_BAD_BREAK;
1483 goto Done;
1484 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001485
Laurence Lundblade02625d42020-06-25 14:41:41 -07001486 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001487 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001488
Laurence Lundblade02625d42020-06-25 14:41:41 -07001489 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001490
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001491 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001492 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001493 /* 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 -07001494 if(bMarkEnd) {
1495 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001496 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001497
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001498 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001499 break;
1500 }
1501
1502 /* Finally, actually ascend one level. */
1503 DecodeNesting_Ascend(&(pMe->nesting));
1504 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001505
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001506 uReturn = QCBOR_SUCCESS;
1507
1508Done:
1509 return uReturn;
1510}
1511
1512
1513/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001514 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001515 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1516 indefinte length maps and arrays by looking at the item count or
1517 finding CBOR breaks. It detects the ends of the top-level sequence
1518 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001519
1520 @retval QCBOR_ERR_UNSUPPORTED X
1521
1522 @retval QCBOR_ERR_HIT_END
1523
1524 @retval QCBOR_ERR_INT_OVERFLOW X
1525
1526 @retval QCBOR_ERR_STRING_ALLOCATE
1527
1528 @retval QCBOR_ERR_STRING_TOO_LONG
1529
1530 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1531
1532 @retval QCBOR_ERR_BAD_TYPE_7 X
1533
1534 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1535
1536 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1537
1538 @retval QCBOR_ERR_TOO_MANY_TAGS
1539
1540 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1541
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001542 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001543
1544 @retval QCBOR_ERR_NO_MORE_ITEMS
1545
1546 @retval QCBOR_ERR_BAD_BREAK
1547
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001548 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001549static QCBORError
1550QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001551{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001552 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001553 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001554
Laurence Lundblade642282a2020-06-23 12:00:33 -07001555 /*
1556 If out of bytes to consume, it is either the end of the top-level
1557 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001558
Laurence Lundblade642282a2020-06-23 12:00:33 -07001559 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1560 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1561 CBOR is exited, the length is set back to the top-level's length
1562 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001563 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001564 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001565 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001566 goto Done;
1567 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001568
Laurence Lundblade642282a2020-06-23 12:00:33 -07001569 /*
1570 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001571 array. The check for the end of an indefinite length array is
1572 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001573 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001574 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001575 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001576 goto Done;
1577 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001578
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001579 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001580 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001581 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1582 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001583 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001584 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301585
Laurence Lundblade642282a2020-06-23 12:00:33 -07001586 /*
1587 Breaks ending arrays/maps are always processed at the end of this
1588 function. They should never show up here.
1589 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301590 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001591 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301592 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301593 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001594
Laurence Lundblade642282a2020-06-23 12:00:33 -07001595 /*
1596 Record the nesting level for this data item before processing any
1597 of decrementing and descending.
1598 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001599 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001600
Laurence Lundblade642282a2020-06-23 12:00:33 -07001601
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001602 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001603 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001604 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001605 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001606
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001607 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001608 of in the next chunk of code.
1609
1610 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001611 encloses them so a decrement needs to be done for them too, but
1612 that is done only when all the items in them have been
1613 processed, not when they are opened with the exception of an
1614 empty map or array.
1615 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001616 QCBORError uDescendErr;
1617 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001618 pDecodedItem->uDataType,
1619 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001620 if(uDescendErr != QCBOR_SUCCESS) {
1621 /* This error is probably a traversal error and it
1622 overrides the non-traversal error. */
1623 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624 goto Done;
1625 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001626 }
1627
Laurence Lundblade02625d42020-06-25 14:41:41 -07001628 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1629 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1630 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001631 /*
1632 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001633 - A non-aggregate like an integer or string
1634 - An empty definite length map or array
1635 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001636
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001637 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001638 definite length map/array and break detection for an indefinite
1639 length map/array. If the end of the map/array was reached, then
1640 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001641 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001642 QCBORError uAscendErr;
1643 uAscendErr = NestLevelAscender(me, true);
1644 if(uAscendErr != QCBOR_SUCCESS) {
1645 /* This error is probably a traversal error and it
1646 overrides the non-traversal error. */
1647 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001648 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001649 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301650 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001651
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001652 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001653 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001654 Tell the caller what level is next. This tells them what
1655 maps/arrays were closed out and makes it possible for them to
1656 reconstruct the tree with just the information returned in
1657 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001659 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001660 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001661 pDecodedItem->uNextNestLevel = 0;
1662 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001663 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001664 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001666Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001667 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001668 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001669 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1670 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1671 // memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001672 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001673 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001674}
1675
Laurence Lundblade9b334962020-08-27 10:55:53 -07001676static void ShiftTags(QCBORItem *pDecodedItem)
1677{
1678 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1679 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1680 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1681 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1682}
1683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001684
Laurence Lundblade59289e52019-12-30 13:44:37 -08001685/*
1686 Mostly just assign the right data type for the date string.
1687 */
1688inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1689{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001690 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1691 return QCBOR_ERR_BAD_OPT_TAG;
1692 }
1693
1694 const UsefulBufC Temp = pDecodedItem->val.string;
1695 pDecodedItem->val.dateString = Temp;
1696 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001697 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001698 return QCBOR_SUCCESS;
1699}
1700
1701
Laurence Lundblade9b334962020-08-27 10:55:53 -07001702
Laurence Lundblade59289e52019-12-30 13:44:37 -08001703/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001704 The epoch formatted date. Turns lots of different forms of encoding
1705 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001706 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001707static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001708{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001709 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710
1711 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1712
1713 switch (pDecodedItem->uDataType) {
1714
1715 case QCBOR_TYPE_INT64:
1716 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1717 break;
1718
1719 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001720 // This only happens for CBOR type 0 > INT64_MAX so it is
1721 // always an overflow.
1722 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1723 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001724 break;
1725
1726 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001727 case QCBOR_TYPE_FLOAT:
1728#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001729 {
1730 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001731 // conversion to an int64_t to be able to detect doubles that
1732 // are too large to fit into an int64_t. A double has 52
1733 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1734 // to a double actually causes a round up which is bad and
1735 // wrong for the comparison because it will allow conversion
1736 // of doubles that can't fit into a uint64_t. To remedy this
1737 // INT64_MAX - 0x7ff is used as the cutoff point because if
1738 // that value rounds up in conversion to double it will still
1739 // be less than INT64_MAX. 0x7ff is picked because it has 11
1740 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001741 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001742 // INT64_MAX seconds is on the order of 10 billion years, and
1743 // the earth is less than 5 billion years old, so for most
1744 // uses this conversion error won't occur even though doubles
1745 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746 //
1747 // Without the 0x7ff there is a ~30 minute range of time
1748 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001749 // where this code would go wrong. Some compilers
1750 // will generate warnings or errors without the 0x7ff
1751 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001752 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1753 pDecodedItem->val.dfnum :
1754 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001755 if(isnan(d) ||
1756 d > (double)(INT64_MAX - 0x7ff) ||
1757 d < (double)(INT64_MIN + 0x7ff)) {
1758 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001759 goto Done;
1760 }
1761 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001762 pDecodedItem->val.epochDate.fSecondsFraction =
1763 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001765#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001766
Laurence Lundbladec7114722020-08-13 05:11:40 -07001767 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001768 goto Done;
1769
Laurence Lundblade9682a532020-06-06 18:33:04 -07001770#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001771 break;
1772
1773 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001774 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001775 goto Done;
1776 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001777
Laurence Lundblade59289e52019-12-30 13:44:37 -08001778 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1779
1780Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001781 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001782}
1783
1784
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001785/*
1786 Mostly just assign the right data type for the bignum.
1787 */
1788inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1789{
1790 // Stack Use: UsefulBuf 1 -- 16
1791 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1792 return QCBOR_ERR_BAD_OPT_TAG;
1793 }
1794 const UsefulBufC Temp = pDecodedItem->val.string;
1795 pDecodedItem->val.bigNum = Temp;
1796 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1797 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1798 : QCBOR_TYPE_NEGBIGNUM);
1799 return QCBOR_SUCCESS;
1800}
1801
1802
Laurence Lundblade59289e52019-12-30 13:44:37 -08001803#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1804/*
1805 Decode decimal fractions and big floats.
1806
1807 When called pDecodedItem must be the array that is tagged as a big
1808 float or decimal fraction, the array that has the two members, the
1809 exponent and mantissa.
1810
1811 This will fetch and decode the exponent and mantissa and put the
1812 result back into pDecodedItem.
1813 */
1814inline static QCBORError
1815QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1816{
1817 QCBORError nReturn;
1818
1819 // --- Make sure it is an array; track nesting level of members ---
1820 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1821 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1822 goto Done;
1823 }
1824
1825 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001826 // definite length arrays, but not for indefnite. Instead remember
1827 // the nesting level the two integers must be at, which is one
1828 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1830
1831 // --- Is it a decimal fraction or a bigfloat? ---
1832 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1833 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1834
1835 // --- Get the exponent ---
1836 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001837 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001838 if(nReturn != QCBOR_SUCCESS) {
1839 goto Done;
1840 }
1841 if(exponentItem.uNestingLevel != nNestLevel) {
1842 // Array is empty or a map/array encountered when expecting an int
1843 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1844 goto Done;
1845 }
1846 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1847 // Data arriving as an unsigned int < INT64_MAX has been converted
1848 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1849 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1850 // will be too large for this to handle and thus an error that will
1851 // get handled in the next else.
1852 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1853 } else {
1854 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1855 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1856 goto Done;
1857 }
1858
1859 // --- Get the mantissa ---
1860 QCBORItem mantissaItem;
1861 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1862 if(nReturn != QCBOR_SUCCESS) {
1863 goto Done;
1864 }
1865 if(mantissaItem.uNestingLevel != nNestLevel) {
1866 // Mantissa missing or map/array encountered when expecting number
1867 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1868 goto Done;
1869 }
1870 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1871 // Data arriving as an unsigned int < INT64_MAX has been converted
1872 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1873 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1874 // will be too large for this to handle and thus an error that
1875 // will get handled in an else below.
1876 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1877 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1878 // Got a good big num mantissa
1879 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1880 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001881 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1882 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1883 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001884 } else {
1885 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1886 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1887 goto Done;
1888 }
1889
1890 // --- Check that array only has the two numbers ---
1891 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001892 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001893 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1894 goto Done;
1895 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001896 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897
1898Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001899 return nReturn;
1900}
1901#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1902
1903
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001904inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1905{
1906 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1907 return QCBOR_ERR_BAD_OPT_TAG;
1908 }
1909 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1910 return QCBOR_SUCCESS;
1911}
1912
1913
1914inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1915{
1916 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1917 return QCBOR_ERR_BAD_OPT_TAG;
1918 }
1919 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001920
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001921 return QCBOR_SUCCESS;
1922}
1923
1924
1925inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1926{
1927 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1928 return QCBOR_ERR_BAD_OPT_TAG;
1929 }
1930 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001931
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001932 return QCBOR_SUCCESS;
1933}
1934
1935
1936inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1937{
1938 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1939 return QCBOR_ERR_BAD_OPT_TAG;
1940 }
1941 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001942
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001943 return QCBOR_SUCCESS;
1944}
1945
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001946
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001947inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1948{
1949 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1950 return QCBOR_ERR_BAD_OPT_TAG;
1951 }
1952 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001953
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001954 return QCBOR_SUCCESS;
1955}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001956
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001957
1958inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1959{
1960 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1961 return QCBOR_ERR_BAD_OPT_TAG;
1962 }
1963 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001964
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001965 return QCBOR_SUCCESS;
1966}
1967
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001968
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001969inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1970{
1971 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1972 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001973 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001974 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1975 } else {
1976 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001977
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001978 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001979
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001980 return QCBOR_SUCCESS;
1981}
1982
1983
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001984inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1985{
1986 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1987 return QCBOR_ERR_BAD_OPT_TAG;
1988 }
1989 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001990
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001991 return QCBOR_SUCCESS;
1992}
1993
1994
Laurence Lundblade59289e52019-12-30 13:44:37 -08001995/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001996 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001997 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001998QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001999QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002000{
2001 QCBORError nReturn;
2002
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002003 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 if(nReturn != QCBOR_SUCCESS) {
2005 goto Done;
2006 }
2007
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002008 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002009 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002010
Laurence Lundblade4a21be12020-08-05 12:48:33 -07002011 // Many of the functions here only just map a CBOR tag to
2012 // a QCBOR_TYPE for a string and could probably be
2013 // implemented with less object code. This implementation
2014 // of string types takes about 120 bytes of object code
2015 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002016 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002017 nReturn = DecodeDateString(pDecodedItem);
2018 break;
2019
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002020 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002021 nReturn = DecodeDateEpoch(pDecodedItem);
2022 break;
2023
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002024 case CBOR_TAG_POS_BIGNUM:
2025 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 nReturn = DecodeBigNum(pDecodedItem);
2027 break;
2028
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002029 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2030 case CBOR_TAG_DECIMAL_FRACTION:
2031 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002032 // For aggregate tagged types, what goes into pTags is only collected
2033 // from the surrounding data item, not the contents, so pTags is not
2034 // passed on here.
2035
2036 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
2037 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002038 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002040 case CBOR_TAG_CBOR:
2041 nReturn = DecodeWrappedCBOR(pDecodedItem);
2042 break;
2043
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002044 case CBOR_TAG_CBOR_SEQUENCE:
2045 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
2046 break;
2047
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002048 case CBOR_TAG_URI:
2049 nReturn = DecodeURI(pDecodedItem);
2050 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002051
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002052 case CBOR_TAG_B64URL:
2053 nReturn = DecodeB64URL(pDecodedItem);
2054 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002055
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002056 case CBOR_TAG_B64:
2057 nReturn = DecodeB64(pDecodedItem);
2058 break;
2059
2060 case CBOR_TAG_MIME:
2061 case CBOR_TAG_BINARY_MIME:
2062 nReturn = DecodeMIME(pDecodedItem);
2063 break;
2064
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002065 case CBOR_TAG_REGEX:
2066 nReturn = DecodeRegex(pDecodedItem);
2067 break;
2068
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002069 case CBOR_TAG_BIN_UUID:
2070 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002071 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002072
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002073 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002074 // The end of the tag list or no tags
2075 // Successful exit from the loop.
2076 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002077
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002078 default:
2079 // A tag that is not understood
2080 // A successful exit from the loop
2081 goto Done;
2082
2083 }
2084 if(nReturn != QCBOR_SUCCESS) {
2085 goto Done;
2086 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002087 // A tag was successfully processed, shift it
2088 // out of the list of tags returned.
2089 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 }
2091
2092Done:
2093 if(nReturn != QCBOR_SUCCESS) {
2094 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2095 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2096 }
2097 return nReturn;
2098}
2099
2100
2101/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002102 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002103 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002104void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2105{
2106 if(pMe->uLastError != QCBOR_SUCCESS) {
2107 return;
2108 }
2109
2110 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2111}
2112
2113
2114/*
2115 Public function, see header qcbor/qcbor_decode.h file
2116 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002117QCBORError
2118QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2119 QCBORItem *pDecodedItem,
2120 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002121{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002122 QCBORError nReturn;
2123
2124 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2125 if(nReturn != QCBOR_SUCCESS) {
2126 return nReturn;
2127 }
2128
2129 if(pTags != NULL) {
2130 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002131 // Reverse the order because pTags is reverse of
2132 // QCBORItem.uTags.
2133 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002134 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002135 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002136 }
2137 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2138 return QCBOR_ERR_TOO_MANY_TAGS;
2139 }
2140 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2141 pTags->uNumUsed++;
2142 }
2143 }
2144
2145 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002146}
2147
2148
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002149/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302150 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302151 next one down. If a layer has no work to do for a particular item
2152 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002153
Laurence Lundblade59289e52019-12-30 13:44:37 -08002154 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2155 tagged data items, turning them into the local C representation.
2156 For the most simple it is just associating a QCBOR_TYPE with the data. For
2157 the complex ones that an aggregate of data items, there is some further
2158 decoding and a little bit of recursion.
2159
2160 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302161 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302162 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002163 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002164
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302165 - GetNext_MapEntry -- This handles the combining of two
2166 items, the label and the data, that make up a map entry.
2167 It only does work on maps. It combines the label and data
2168 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002169
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2171 tags into bit flags associated with the data item. No actual decoding
2172 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002173
Laurence Lundblade59289e52019-12-30 13:44:37 -08002174 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302175 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302176 string allocater to create contiguous space for the item. It
2177 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002178
Laurence Lundblade59289e52019-12-30 13:44:37 -08002179 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2180 atomic data item has a "major type", an integer "argument" and optionally
2181 some content. For text and byte strings, the content is the bytes
2182 that make up the string. These are the smallest data items that are
2183 considered to be well-formed. The content may also be other data items in
2184 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002185
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002186 Roughly this takes 300 bytes of stack for vars. Need to
2187 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002188
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302189 */
2190
2191
2192/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002193 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002194 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002195bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002196 const QCBORItem *pItem,
2197 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002198{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002199 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002200 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002201 break;
2202 }
2203 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002204 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002205 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002206 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002207
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002208 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002209}
2210
2211
2212/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002213 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002214 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002215QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002216{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002217 QCBORError uReturn = me->uLastError;
2218
2219 if(uReturn != QCBOR_SUCCESS) {
2220 goto Done;
2221 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002223 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002224 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002225 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002226 goto Done;
2227 }
2228
2229 // Error out if not all the bytes are consumed
2230 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002231 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002234Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302235 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002236 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002237 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002238
Laurence Lundblade085d7952020-07-24 10:26:30 -07002239 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002240}
2241
2242
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002243/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002244 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002245*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002246// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002247uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2248 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002249 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002250{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002251 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2252 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002253 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002254 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002255 }
2256}
2257
Laurence Lundblade9b334962020-08-27 10:55:53 -07002258/*
2259 Public function, see header qcbor/qcbor_decode.h file
2260*/
2261uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2262 uint32_t uIndex)
2263{
2264 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2265 return CBOR_TAG_INVALID64;
2266 } else {
2267 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2268 }
2269}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002270
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271/*
2272
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002273Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275 - Hit end of input before it was expected while decoding type and
2276 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002277
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002278 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundbladeee851742020-01-08 08:37:05 -08002280 - Hit end of input while decoding a text or byte string
2281 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002282
Laurence Lundbladeee851742020-01-08 08:37:05 -08002283 - Encountered conflicting tags -- e.g., an item is tagged both a date
2284 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002285
Laurence Lundbladeee851742020-01-08 08:37:05 -08002286 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002287 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002288
Laurence Lundbladeee851742020-01-08 08:37:05 -08002289 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002290 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002291
Laurence Lundbladeee851742020-01-08 08:37:05 -08002292 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2293 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294
Laurence Lundbladeee851742020-01-08 08:37:05 -08002295 - The type of a map label is not a string or int
2296 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002297
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002298 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002299
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002300 */
2301
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002302
2303
Laurence Lundbladef6531662018-12-04 10:42:22 +09002304
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002305/* ===========================================================================
2306 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002307
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002308 This implements a simple sting allocator for indefinite length
2309 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2310 implements the function type QCBORStringAllocate and allows easy
2311 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002312
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002313 This particular allocator is built-in for convenience. The caller
2314 can implement their own. All of this following code will get
2315 dead-stripped if QCBORDecode_SetMemPool() is not called.
2316
2317 This is a very primitive memory allocator. It does not track
2318 individual allocations, only a high-water mark. A free or
2319 reallocation must be of the last chunk allocated.
2320
2321 The size of the pool and offset to free memory are packed into the
2322 first 8 bytes of the memory pool so we don't have to keep them in
2323 the decode context. Since the address of the pool may not be
2324 aligned, they have to be packed and unpacked as if they were
2325 serialized data of the wire or such.
2326
2327 The sizes packed in are uint32_t to be the same on all CPU types
2328 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002329 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002330
2331
Laurence Lundbladeee851742020-01-08 08:37:05 -08002332static inline int
2333MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002334{
2335 // Use of UsefulInputBuf is overkill, but it is convenient.
2336 UsefulInputBuf UIB;
2337
Laurence Lundbladeee851742020-01-08 08:37:05 -08002338 // Just assume the size here. It was checked during SetUp so
2339 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002340 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2341 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2342 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2343 return UsefulInputBuf_GetError(&UIB);
2344}
2345
2346
Laurence Lundbladeee851742020-01-08 08:37:05 -08002347static inline int
2348MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002349{
2350 // Use of UsefulOutBuf is overkill, but convenient. The
2351 // length check performed here is useful.
2352 UsefulOutBuf UOB;
2353
2354 UsefulOutBuf_Init(&UOB, Pool);
2355 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2356 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2357 return UsefulOutBuf_GetError(&UOB);
2358}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002359
2360
2361/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002362 Internal function for an allocation, reallocation free and destuct.
2363
2364 Having only one function rather than one each per mode saves space in
2365 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002366
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002367 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2368 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002369static UsefulBuf
2370MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002371{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002372 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002373
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002374 uint32_t uPoolSize;
2375 uint32_t uFreeOffset;
2376
2377 if(uNewSize > UINT32_MAX) {
2378 // This allocator is only good up to 4GB. This check should
2379 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2380 goto Done;
2381 }
2382 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2383
2384 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2385 goto Done;
2386 }
2387
2388 if(uNewSize) {
2389 if(pMem) {
2390 // REALLOCATION MODE
2391 // Calculate pointer to the end of the memory pool. It is
2392 // assumed that pPool + uPoolSize won't wrap around by
2393 // assuming the caller won't pass a pool buffer in that is
2394 // not in legitimate memory space.
2395 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2396
2397 // Check that the pointer for reallocation is in the range of the
2398 // pool. This also makes sure that pointer math further down
2399 // doesn't wrap under or over.
2400 if(pMem >= pPool && pMem < pPoolEnd) {
2401 // Offset to start of chunk for reallocation. This won't
2402 // wrap under because of check that pMem >= pPool. Cast
2403 // is safe because the pool is always less than UINT32_MAX
2404 // because of check in QCBORDecode_SetMemPool().
2405 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2406
2407 // Check to see if the allocation will fit. uPoolSize -
2408 // uMemOffset will not wrap under because of check that
2409 // pMem is in the range of the uPoolSize by check above.
2410 if(uNewSize <= uPoolSize - uMemOffset) {
2411 ReturnValue.ptr = pMem;
2412 ReturnValue.len = uNewSize;
2413
2414 // Addition won't wrap around over because uNewSize was
2415 // checked to be sure it is less than the pool size.
2416 uFreeOffset = uMemOffset + uNewSize32;
2417 }
2418 }
2419 } else {
2420 // ALLOCATION MODE
2421 // uPoolSize - uFreeOffset will not underflow because this
2422 // pool implementation makes sure uFreeOffset is always
2423 // smaller than uPoolSize through this check here and
2424 // reallocation case.
2425 if(uNewSize <= uPoolSize - uFreeOffset) {
2426 ReturnValue.len = uNewSize;
2427 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002428 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002429 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002430 }
2431 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002432 if(pMem) {
2433 // FREE MODE
2434 // Cast is safe because of limit on pool size in
2435 // QCBORDecode_SetMemPool()
2436 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2437 } else {
2438 // DESTRUCT MODE
2439 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002440 }
2441 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002442
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002443 UsefulBuf Pool = {pPool, uPoolSize};
2444 MemPool_Pack(Pool, uFreeOffset);
2445
2446Done:
2447 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002448}
2449
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002450
Laurence Lundbladef6531662018-12-04 10:42:22 +09002451/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002452 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002453 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002454QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2455 UsefulBuf Pool,
2456 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002457{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002458 // The pool size and free mem offset are packed into the beginning
2459 // of the pool memory. This compile time check make sure the
2460 // constant in the header is correct. This check should optimize
2461 // down to nothing.
2462 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002463 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002464 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002465
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002466 // The pool size and free offset packed in to the beginning of pool
2467 // memory are only 32-bits. This check will optimize out on 32-bit
2468 // machines.
2469 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002470 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002471 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002472
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002473 // This checks that the pool buffer given is big enough.
2474 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002475 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002477
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002478 pMe->StringAllocator.pfAllocator = MemPool_Function;
2479 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2480 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002481
Laurence Lundblade30816f22018-11-10 13:40:22 +07002482 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002483}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002484
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002485
2486
Laurence Lundblade9b334962020-08-27 10:55:53 -07002487static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2488{
2489 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2490}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002491
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002492
2493/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002494 Consume an entire map or array (and do next to
2495 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002496 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002497static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002498ConsumeItem(QCBORDecodeContext *pMe,
2499 const QCBORItem *pItemToConsume,
2500 uint_fast8_t *puNextNestLevel)
2501{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002502 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002503 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002504
Laurence Lundblade02625d42020-06-25 14:41:41 -07002505 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002506
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002507 // If it is a map or array, this will tell if it is empty.
2508 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2509
2510 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2511 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002512
Laurence Lundblade1341c592020-04-11 14:19:05 -07002513 /* This works for definite and indefinite length
2514 * maps and arrays by using the nesting level
2515 */
2516 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002517 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002518 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002519 goto Done;
2520 }
2521 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002522
Laurence Lundblade1341c592020-04-11 14:19:05 -07002523 if(puNextNestLevel != NULL) {
2524 *puNextNestLevel = Item.uNextNestLevel;
2525 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002526 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002527
Laurence Lundblade1341c592020-04-11 14:19:05 -07002528 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002529 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530 if(puNextNestLevel != NULL) {
2531 /* Just pass the nesting level through */
2532 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2533 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002534 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002536
2537Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002538 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002539}
2540
2541
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542/* Return true if the labels in Item1 and Item2 are the same.
2543 Works only for integer and string labels. Returns false
2544 for any other type. */
2545static inline bool
2546MatchLabel(QCBORItem Item1, QCBORItem Item2)
2547{
2548 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2549 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2550 return true;
2551 }
2552 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002554 return true;
2555 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002556 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002557 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2558 return true;
2559 }
2560 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2561 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2562 return true;
2563 }
2564 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002565
Laurence Lundblade1341c592020-04-11 14:19:05 -07002566 /* Other label types are never matched */
2567 return false;
2568}
2569
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002570
2571/*
2572 Returns true if Item1 and Item2 are the same type
2573 or if either are of QCBOR_TYPE_ANY.
2574 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002575static inline bool
2576MatchType(QCBORItem Item1, QCBORItem Item2)
2577{
2578 if(Item1.uDataType == Item2.uDataType) {
2579 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002580 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002581 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002582 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002583 return true;
2584 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002585 return false;
2586}
2587
2588
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002589/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002590 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002591
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002592 @param[in] pMe The decode context to search.
2593 @param[in,out] pItemArray The items to search for and the items found.
2594 @param[out] puOffset Byte offset of last item matched.
2595 @param[in] pCBContext Context for the not-found item call back.
2596 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002597
2598 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2599
Laurence Lundblade9b334962020-08-27 10:55:53 -07002600 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2601 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2602 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002603
2604 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2605
2606 @retval Also errors returned by QCBORDecode_GetNext().
2607
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002608 On input pItemArray contains a list of labels and data types
2609 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002610
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002611 On output the fully retrieved items are filled in with
2612 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002613
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002614 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002615 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002616// TODO: make this handle indefinite length strings, possibly with
2617// allocation only when returning the string.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002618static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002619MapSearch(QCBORDecodeContext *pMe,
2620 QCBORItem *pItemArray,
2621 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002622 void *pCBContext,
2623 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002624{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002625 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002626 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002627
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002628 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002629 uReturn = pMe->uLastError;
2630 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002631 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002632
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002633 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002634 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2635 /* QCBOR_TYPE_NONE as first item indicates just looking
2636 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002637 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2638 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002639 }
2640
Laurence Lundblade085d7952020-07-24 10:26:30 -07002641 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2642 // It is an empty bounded array or map
2643 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2644 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002645 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002646 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002647 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002648 // Nothing is ever found in an empty array or map. All items
2649 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002650 uReturn = QCBOR_SUCCESS;
2651 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002652 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002653 }
2654
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002655 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002656 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2657
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002658 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002659 UsefulInputBuf_Seek(&(pMe->InBuf),
2660 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002661
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002662 /*
2663 Loop over all the items in the map. They could be
2664 deeply nested and this should handle both definite
2665 and indefinite length maps and arrays, so this
2666 adds some complexity.
2667 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002668 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002669 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002670 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002671 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002672 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002673
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002674 /* Get the item */
2675 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002676 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002677 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002678 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002679 goto Done;
2680 }
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002681 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2682 // Unexpected end of map or array.
2683 goto Done;
2684 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002685
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002686 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002687 bool bMatched = false;
2688 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002689 // TODO: have label filled in on invalid CBOR so error reporting
Laurence Lundblade9b334962020-08-27 10:55:53 -07002690 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002691 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002692 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002693 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2694 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002695 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002696 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002697 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002698 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002699 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002700 goto Done;
2701 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002702
Laurence Lundblade1341c592020-04-11 14:19:05 -07002703 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002704 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002705 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002706 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002707 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002708 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002709 bMatched = true;
2710 }
2711 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002712
2713
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002714 if(!bMatched && pfCallback != NULL) {
2715 /*
2716 Call the callback on unmatched labels.
2717 (It is tempting to do duplicate detection here, but that would
2718 require dynamic memory allocation because the number of labels
2719 that might be encountered is unbounded.)
2720 */
2721 uReturn = (*pfCallback)(pCBContext, &Item);
2722 if(uReturn != QCBOR_SUCCESS) {
2723 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002724 }
2725 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002726
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002727 /*
2728 Consume the item whether matched or not. This
2729 does the work of traversing maps and array and
2730 everything in them. In this loop only the
2731 items at the current nesting level are examined
2732 to match the labels.
2733 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002734 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002735 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002736 goto Done;
2737 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002738
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002739 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002740
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002741 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002742
2743 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002744 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2745 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002746
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002747 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002748 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2749
2750 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002751 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2752 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002753 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002754 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755 }
2756 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002757
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002758 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759}
2760
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002761
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 Lundblade843a10c2020-05-23 13:57:00 -07002765void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2766 int64_t nLabel,
2767 uint8_t uQcborType,
2768 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002769{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002770 if(pMe->uLastError != QCBOR_SUCCESS) {
2771 return;
2772 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002774 QCBORItem OneItemSeach[2];
2775 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2776 OneItemSeach[0].label.int64 = nLabel;
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 Lundblade843a10c2020-05-23 13:57:00 -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 Lundblade843a10c2020-05-23 13:57:00 -07002789 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002790
2791 Done:
2792 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002793}
2794
2795
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002796/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002797 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002798*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002799void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2800 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002801 uint8_t uQcborType,
2802 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002803{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002804 if(pMe->uLastError != QCBOR_SUCCESS) {
2805 return;
2806 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002808 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002809 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2810 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2811 OneItemSeach[0].uDataType = uQcborType;
2812 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002813
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002814 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2815 if(uReturn != QCBOR_SUCCESS) {
2816 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002817 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002818 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002819 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002820 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002821 }
2822
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002823 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002824
2825Done:
2826 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002827}
2828
2829
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002830
Laurence Lundblade9b334962020-08-27 10:55:53 -07002831static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002832{
2833 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2834 if(uDataType == puTypeList[i]) {
2835 return QCBOR_SUCCESS;
2836 }
2837 }
2838 return QCBOR_ERR_UNEXPECTED_TYPE;
2839}
2840
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002841
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002842/**
2843 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002844 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002845
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002846 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2847 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002848
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002849 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2850 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002851static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002852{
2853 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2854 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2855 /* There are tags that QCBOR couldn't process on this item and
2856 the caller has told us there should not be. */
2857 return QCBOR_ERR_UNEXPECTED_TYPE;
2858 }
2859
2860 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2861 const int nItemType = pItem->uDataType;
2862
2863 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2864 // Must match the tag and only the tag
2865 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2866 }
2867
2868 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2869 if(uReturn == QCBOR_SUCCESS) {
2870 return QCBOR_SUCCESS;
2871 }
2872
2873 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2874 /* Must match the content type and only the content type.
2875 There was no match just above so it is a fail. */
2876 return QCBOR_ERR_UNEXPECTED_TYPE;
2877 }
2878
2879 /* If here it can match either the tag or the content
2880 and it hasn't matched the content, so the end
2881 result is whether it matches the tag. This is
2882 also the case that the CBOR standard discourages. */
2883
2884 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2885}
2886
Laurence Lundblade9b334962020-08-27 10:55:53 -07002887
Laurence Lundblade9b334962020-08-27 10:55:53 -07002888
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002889// This could be semi-private if need be
2890static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002891void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2892 int64_t nLabel,
2893 TagSpecification TagSpec,
2894 QCBORItem *pItem)
2895{
2896 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2897 if(pMe->uLastError != QCBOR_SUCCESS) {
2898 return;
2899 }
2900
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002901 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002902}
2903
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002904
2905// This could be semi-private if need be
2906static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002907void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2908 const char *szLabel,
2909 TagSpecification TagSpec,
2910 QCBORItem *pItem)
2911{
2912 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2913 if(pMe->uLastError != QCBOR_SUCCESS) {
2914 return;
2915 }
2916
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002917 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002918}
2919
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002920// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002921void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2922 int64_t nLabel,
2923 TagSpecification TagSpec,
2924 UsefulBufC *pString)
2925{
2926 QCBORItem Item;
2927 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2928 if(pMe->uLastError == QCBOR_SUCCESS) {
2929 *pString = Item.val.string;
2930 }
2931}
2932
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002933// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002934void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2935 const char * szLabel,
2936 TagSpecification TagSpec,
2937 UsefulBufC *pString)
2938{
2939 QCBORItem Item;
2940 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2941 if(pMe->uLastError == QCBOR_SUCCESS) {
2942 *pString = Item.val.string;
2943 }
2944}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002945
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002946/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002947 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002948*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002949void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002950{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002951 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2952 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002953}
2954
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002955/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002956 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002957*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002958void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2959 QCBORItem *pItemList,
2960 void *pCallbackCtx,
2961 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002962{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002963 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2964 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002965}
2966
2967
Laurence Lundblade34691b92020-05-18 22:25:25 -07002968static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002969{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002970 // The first item in pSearch is the one that is to be
2971 // entered. It should be the only one filled in. Any other
2972 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002973 if(pMe->uLastError != QCBOR_SUCCESS) {
2974 // Already in error state; do nothing.
2975 return;
2976 }
2977
2978 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002979 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002980 if(pMe->uLastError != QCBOR_SUCCESS) {
2981 return;
2982 }
2983
Laurence Lundblade9b334962020-08-27 10:55:53 -07002984 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002985 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002986 return;
2987 }
2988
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002989 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002990 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002991
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002992 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002993 be at the right place.
2994
2995 The UsefulInBuf offset could be anywhere, so no assumption is
2996 made about it.
2997
2998 No assumption is made about the pre-order nesting level either.
2999
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003000 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003001 the map level that is being entered.
3002 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003003 /* Seek to the data item that is the map or array */
3004 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003005
3006 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003007
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003008 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003009}
3010
3011
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003012/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003013 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003014*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003015void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003016{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003017 QCBORItem OneItemSeach[2];
3018 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3019 OneItemSeach[0].label.int64 = nLabel;
3020 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3021 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003022
Laurence Lundblade9b334962020-08-27 10:55:53 -07003023 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003024 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003025}
3026
3027
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003028/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003029 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003030*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003031void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003032{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003033 QCBORItem OneItemSeach[2];
3034 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3035 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3036 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3037 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003038
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003039 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003040}
3041
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003042/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003043 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003044*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003045void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003047 QCBORItem OneItemSeach[2];
3048 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3049 OneItemSeach[0].label.int64 = nLabel;
3050 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3051 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003052
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003053 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003054}
3055
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003056/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003057 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003058*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003059void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3060{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003061 QCBORItem OneItemSeach[2];
3062 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3063 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3064 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3065 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003066
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003067 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003068}
3069
3070
Laurence Lundblade02625d42020-06-25 14:41:41 -07003071// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003072void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003073{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003074 QCBORError uErr;
3075
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003076 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003077 if(pMe->uLastError != QCBOR_SUCCESS) {
3078 // Already in error state; do nothing.
3079 return;
3080 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003081
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003082 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003083 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003084 uErr = QCBORDecode_GetNext(pMe, &Item);
3085 if(uErr != QCBOR_SUCCESS) {
3086 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003087 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003088 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003089 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3090 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003091 }
3092
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003093 CopyTags(pMe, &Item);
3094
3095
Laurence Lundbladef0499502020-08-01 11:55:57 -07003096 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003097 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003098 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3099 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003100 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003101 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3102 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003103 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3104 DecodeNesting_Descend(&(pMe->nesting), uType);
3105 }
3106
Laurence Lundblade02625d42020-06-25 14:41:41 -07003107 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003108
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003109 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3110 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003111
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003112Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003113 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003114}
3115
Laurence Lundblade02625d42020-06-25 14:41:41 -07003116
3117/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003118 This is the common work for exiting a level that is a bounded map, array or bstr
3119 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003120
3121 One chunk of work is to set up the pre-order traversal so it is at
3122 the item just after the bounded map, array or bstr that is being
3123 exited. This is somewhat complex.
3124
3125 The other work is to level-up the bounded mode to next higest bounded
3126 mode or the top level if there isn't one.
3127 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003128static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003129ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003130{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003131 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003132
Laurence Lundblade02625d42020-06-25 14:41:41 -07003133 /*
3134 First the pre-order-traversal byte offset is positioned to the
3135 item just after the bounded mode item that was just consumed.
3136 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003137 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3138
Laurence Lundblade02625d42020-06-25 14:41:41 -07003139 /*
3140 Next, set the current nesting level to one above the bounded level
3141 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003142
Laurence Lundblade02625d42020-06-25 14:41:41 -07003143 DecodeNesting_CheckBoundedType() is always called before this and
3144 makes sure pCurrentBounded is valid.
3145 */
3146 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3147
3148 /*
3149 This does the complex work of leveling up the pre-order traversal
3150 when the end of a map or array or another bounded level is
3151 reached. It may do nothing, or ascend all the way to the top
3152 level.
3153 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003154 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003155 if(uErr != QCBOR_SUCCESS) {
3156 goto Done;
3157 }
3158
Laurence Lundblade02625d42020-06-25 14:41:41 -07003159 /*
3160 This makes the next highest bounded level the current bounded
3161 level. If there is no next highest level, then no bounded mode is
3162 in effect.
3163 */
3164 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003165
Laurence Lundblade02625d42020-06-25 14:41:41 -07003166 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003167
3168Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003169 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003170 return uErr;
3171}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003172
Laurence Lundblade02625d42020-06-25 14:41:41 -07003173
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003174// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003175void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003176{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003177 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003178 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003179 return;
3180 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003181
Laurence Lundblade02625d42020-06-25 14:41:41 -07003182 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003183
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003184 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003185 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003186 goto Done;
3187 }
3188
Laurence Lundblade02625d42020-06-25 14:41:41 -07003189 /*
3190 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003191 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003192 from previous map search, then do a dummy search.
3193 */
3194 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003195 QCBORItem Dummy;
3196 Dummy.uLabelType = QCBOR_TYPE_NONE;
3197 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3198 if(uErr != QCBOR_SUCCESS) {
3199 goto Done;
3200 }
3201 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003202
Laurence Lundblade02625d42020-06-25 14:41:41 -07003203 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003204
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003205Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003206 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003207}
3208
3209
Laurence Lundblade1341c592020-04-11 14:19:05 -07003210
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003211static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003212 const QCBORItem *pItem,
3213 uint8_t uTagRequirement,
3214 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003215{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003216 if(pBstr) {
3217 *pBstr = NULLUsefulBufC;
3218 }
3219
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003220 if(pMe->uLastError != QCBOR_SUCCESS) {
3221 // Already in error state; do nothing.
3222 return pMe->uLastError;
3223 }
3224
3225 QCBORError uError = QCBOR_SUCCESS;
3226
3227 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3228 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3229 goto Done;;
3230 }
3231
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003232 const TagSpecification TagSpec =
3233 {
3234 uTagRequirement,
3235 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3236 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3237 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003238
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003239 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003240 if(uError != QCBOR_SUCCESS) {
3241 goto Done;
3242 }
3243
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003244 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003245 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003246 so the increment in NestLevelAscender called by ExitBoundedLevel()
3247 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003248 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003249 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003250
3251 if(pBstr) {
3252 *pBstr = pItem->val.string;
3253 }
3254
3255 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003256
3257 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003258 // Most of these calls are simple inline accessors so this doesn't
3259 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003260 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003261 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3262 // TODO: test this error condition
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003263 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003264 goto Done;
3265 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003266 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003267 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003268
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003269 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003270 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003271 (uint32_t)uPreviousLength,
3272 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003273Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003274 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003275
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003276 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003277}
3278
3279
Laurence Lundblade02625d42020-06-25 14:41:41 -07003280/*
3281 Public function, see header qcbor/qcbor_decode.h file
3282 */
3283void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003284 uint8_t uTagRequirement,
3285 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003286{
3287 if(pMe->uLastError != QCBOR_SUCCESS) {
3288 // Already in error state; do nothing.
3289 return;
3290 }
3291
3292 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003293 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003294 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3295 if(pMe->uLastError != QCBOR_SUCCESS) {
3296 return;
3297 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003298
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003299 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003300 &Item,
3301 uTagRequirement,
3302 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003303}
3304
3305
Laurence Lundblade02625d42020-06-25 14:41:41 -07003306/*
3307 Public function, see header qcbor/qcbor_decode.h file
3308 */
3309void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003310 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003311 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003312 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003313{
3314 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003315 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003316
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003317 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003318}
3319
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003320
Laurence Lundblade02625d42020-06-25 14:41:41 -07003321/*
3322 Public function, see header qcbor/qcbor_decode.h file
3323 */
3324void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003326 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003327 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003328{
3329 QCBORItem Item;
3330 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3331
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003332 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003333}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003334
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003335
Laurence Lundblade02625d42020-06-25 14:41:41 -07003336/*
3337 Public function, see header qcbor/qcbor_decode.h file
3338 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003339void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003340{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003341 if(pMe->uLastError != QCBOR_SUCCESS) {
3342 // Already in error state; do nothing.
3343 return;
3344 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003345
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003346 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003347 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003348 return;
3349 }
3350
3351 /*
3352 Reset the length of the UsefulInputBuf to what it was before
3353 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003354 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003355 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3356 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003357
3358
Laurence Lundblade02625d42020-06-25 14:41:41 -07003359 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003360 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003361}
3362
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003363
Laurence Lundbladee6430642020-03-14 21:15:44 -07003364
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003365
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003366
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003367
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003368
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003369
Laurence Lundblade9b334962020-08-27 10:55:53 -07003370static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003371{
3372 switch(pItem->uDataType) {
3373 case QCBOR_TYPE_TRUE:
3374 *pBool = true;
3375 return QCBOR_SUCCESS;
3376 break;
3377
3378 case QCBOR_TYPE_FALSE:
3379 *pBool = false;
3380 return QCBOR_SUCCESS;
3381 break;
3382
3383 default:
3384 return QCBOR_ERR_UNEXPECTED_TYPE;
3385 break;
3386 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003387 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003388}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003389
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003390
Laurence Lundblade9b334962020-08-27 10:55:53 -07003391
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003392/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003393 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003394*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003395void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003397 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003398 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003399 return;
3400 }
3401
Laurence Lundbladec4537442020-04-14 18:53:22 -07003402 QCBORError nError;
3403 QCBORItem Item;
3404
3405 nError = QCBORDecode_GetNext(pMe, &Item);
3406 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003407 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003408 return;
3409 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003410 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003411}
3412
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003413
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003414/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003415 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003416*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003417void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003418{
3419 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003420 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003421
Laurence Lundblade9b334962020-08-27 10:55:53 -07003422 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003423}
3424
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003425
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003426/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003427 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003428*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003429void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3430{
3431 QCBORItem Item;
3432 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3433
Laurence Lundblade9b334962020-08-27 10:55:53 -07003434 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003435}
3436
3437
3438
Laurence Lundblade9b334962020-08-27 10:55:53 -07003439/*
3440 A number of methods decode CBOR that is associated with a
3441 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003442
Laurence Lundblade9b334962020-08-27 10:55:53 -07003443 The API of the method returns the
3444 data in a way specific to the
3445
3446 No tags at all.
3447
3448
3449 Require tag for the particular type for the method and no other.
3450
3451
3452 Either no tags at all or the particular type for the method and no other.
3453
3454 No tag for particular type; pass other tags along.
3455
3456 Require the tag for the particular type; pass other tags along
3457
3458 Any tagging is OK; consume the tag for the particular type if present,
3459 pass other tags along.
3460
3461
3462 1) REQUIRED
3463- 1 XXXX -- works
3464- T 1 XXX -- works, T is returned
3465
3466 if(tag is of interest) {
3467 process content
3468 return T if present
3469 }
3470
3471
3472 2) FORBIDDEN
3473 - XXX -- works
3474 - T XXX -- ???
3475
3476 if(tag is of interest) {
3477 error out since tag is forbidden
3478 } else {
3479 process contents
3480 return T
3481 }
3482
3483 3) OPTIONAL
3484 - XXX works
3485 - 1 XXX works
3486 - T XXX
3487 - T 1 XXX works, T is returned
3488
3489if (inner tag is of interest) {
3490 process content
3491 return tag T if present
3492 } else if (there is no tag) {
3493 process content
3494 } else {
3495 process content if possible
3496 return T
3497 }
3498
3499A field is type X
3500 - tag for type X is REQUIRED
3501 - tag for type X is FORBIDDEN
3502 - tag for type X is optional
3503 - Other tags are FORBIDDEN
3504 - Other tags are ALLOWED
3505
3506
3507
3508 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003509
3510static void ProcessEpochDate(QCBORDecodeContext *pMe,
3511 QCBORItem *pItem,
3512 uint8_t uTagRequirement,
3513 int64_t *pnTime)
3514{
3515 if(pMe->uLastError != QCBOR_SUCCESS) {
3516 // Already in error state, do nothing
3517 return;
3518 }
3519
3520 QCBORError uErr;
3521
3522 const TagSpecification TagSpec =
3523 {
3524 uTagRequirement,
3525 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3526 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3527 };
3528
Laurence Lundblade4b270642020-08-14 12:53:07 -07003529 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003530 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3531 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003532 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003533 if(uErr != QCBOR_SUCCESS) {
3534 goto Done;
3535 }
3536
3537 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3538 uErr = DecodeDateEpoch(pItem);
3539 if(uErr != QCBOR_SUCCESS) {
3540 goto Done;
3541 }
3542 }
3543
Laurence Lundblade9b334962020-08-27 10:55:53 -07003544 // Save the tags in the last item's tags in the decode context
3545 // for QCBORDecode_GetNthTagOfLast()
3546 CopyTags(pMe, pItem);
3547
Laurence Lundbladec7114722020-08-13 05:11:40 -07003548 *pnTime = pItem->val.epochDate.nSeconds;
3549
3550Done:
3551 pMe->uLastError = (uint8_t)uErr;
3552}
3553
3554
3555void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3556 uint8_t uTagRequirement,
3557 int64_t *pnTime)
3558{
3559 if(pMe->uLastError != QCBOR_SUCCESS) {
3560 // Already in error state, do nothing
3561 return;
3562 }
3563
3564 QCBORItem Item;
3565 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3566
3567 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3568}
3569
3570
3571void
3572QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3573 int64_t nLabel,
3574 uint8_t uTagRequirement,
3575 int64_t *pnTime)
3576{
3577 QCBORItem Item;
3578 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3579 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3580}
3581
3582
3583void
3584QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3585 const char *szLabel,
3586 uint8_t uTagRequirement,
3587 int64_t *pnTime)
3588{
3589 QCBORItem Item;
3590 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3591 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3592}
3593
3594
3595
3596
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003597void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3598 TagSpecification TagSpec,
3599 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003600{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003601 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003602 // Already in error state, do nothing
3603 return;
3604 }
3605
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003606 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003607 QCBORItem Item;
3608
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003609 uError = QCBORDecode_GetNext(pMe, &Item);
3610 if(uError != QCBOR_SUCCESS) {
3611 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003612 return;
3613 }
3614
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003615 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003616
3617 if(pMe->uLastError == QCBOR_SUCCESS) {
3618 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003619 } else {
3620 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003621 }
3622}
3623
Laurence Lundbladec4537442020-04-14 18:53:22 -07003624
3625
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003626
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003627static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003628 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003629 UsefulBufC *pValue,
3630 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003631{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003632 const TagSpecification TagSpec =
3633 {
3634 uTagRequirement,
3635 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3636 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3637 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003638
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003639 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003640 if(uErr != QCBOR_SUCCESS) {
3641 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003642 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003643
3644 *pValue = pItem->val.string;
3645
3646 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3647 *pbIsNegative = false;
3648 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3649 *pbIsNegative = true;
3650 }
3651
3652 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003653}
3654
3655
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003656/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003657 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003658 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003659void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3660 uint8_t uTagRequirement,
3661 UsefulBufC *pValue,
3662 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003663{
3664 if(pMe->uLastError != QCBOR_SUCCESS) {
3665 // Already in error state, do nothing
3666 return;
3667 }
3668
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003669 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003670 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3671 if(uError != QCBOR_SUCCESS) {
3672 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003673 return;
3674 }
3675
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003676 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003677}
3678
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003679
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003680/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003681 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003682*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003683void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3684 int64_t nLabel,
3685 uint8_t uTagRequirement,
3686 UsefulBufC *pValue,
3687 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003688{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003689 QCBORItem Item;
3690 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003691 if(pMe->uLastError != QCBOR_SUCCESS) {
3692 return;
3693 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003694
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003695 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003696}
3697
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003698
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003699/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003700 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003701*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003702void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3703 const char *szLabel,
3704 uint8_t uTagRequirement,
3705 UsefulBufC *pValue,
3706 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003707{
3708 QCBORItem Item;
3709 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003710 if(pMe->uLastError != QCBOR_SUCCESS) {
3711 return;
3712 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003713
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003714 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003715}
3716
3717
3718
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003719
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003720// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003721QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3722 const QCBORItem *pItem,
3723 UsefulBufC *pMessage,
3724 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003725{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003726 const TagSpecification TagSpecText =
3727 {
3728 uTagRequirement,
3729 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3730 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3731 };
3732 const TagSpecification TagSpecBinary =
3733 {
3734 uTagRequirement,
3735 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3736 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3737 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003738
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003739 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003740
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003741 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003742 *pMessage = pItem->val.string;
3743 if(pbIsNot7Bit != NULL) {
3744 *pbIsNot7Bit = false;
3745 }
3746 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003747 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003748 *pMessage = pItem->val.string;
3749 if(pbIsNot7Bit != NULL) {
3750 *pbIsNot7Bit = true;
3751 }
3752 uReturn = QCBOR_SUCCESS;
3753
3754 } else {
3755 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3756 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003757
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003758 return uReturn;
3759}
3760
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003761// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3762
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003763
3764
3765
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003766#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003767
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003768typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003769
3770
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003771// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003772static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003773{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003774 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003775
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003776 if(uResult != 0) {
3777 /* This loop will run a maximum of 19 times because
3778 * UINT64_MAX < 10 ^^ 19. More than that will cause
3779 * exit with the overflow error
3780 */
3781 for(; nExponent > 0; nExponent--) {
3782 if(uResult > UINT64_MAX / 10) {
3783 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3784 }
3785 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003786 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003787
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003788 for(; nExponent < 0; nExponent++) {
3789 uResult = uResult / 10;
3790 if(uResult == 0) {
3791 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3792 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003793 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003794 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003795 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003796
3797 *puResult = uResult;
3798
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003799 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003800}
3801
3802
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003803// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003804static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003805{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003806 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003807
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003808 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003809
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003810 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003811 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003812 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003813 */
3814 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003815 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003817 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003818 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003819 nExponent--;
3820 }
3821
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003822 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003823 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003824 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3825 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003826 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003827 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828 }
3829
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003830 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003831
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003832 return QCBOR_SUCCESS;
3833}
3834
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003835
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003836/*
3837 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3838 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003839static inline QCBORError ExponentiateNN(int64_t nMantissa,
3840 int64_t nExponent,
3841 int64_t *pnResult,
3842 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003843{
3844 uint64_t uResult;
3845
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003846 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003847 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003848 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3849
3850 // Do the exponentiation of the positive mantissa
3851 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3852 if(uReturn) {
3853 return uReturn;
3854 }
3855
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003856
Laurence Lundblade983500d2020-05-14 11:49:34 -07003857 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3858 of INT64_MIN. This assumes two's compliment representation where
3859 INT64_MIN is one increment farther from 0 than INT64_MAX.
3860 Trying to write -INT64_MIN doesn't work to get this because the
3861 compiler tries to work with an int64_t which can't represent
3862 -INT64_MIN.
3863 */
3864 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3865
3866 // Error out if too large
3867 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3869 }
3870
3871 // Casts are safe because of checks above
3872 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3873
3874 return QCBOR_SUCCESS;
3875}
3876
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003877
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003878/*
3879 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3880 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003881static inline QCBORError ExponentitateNU(int64_t nMantissa,
3882 int64_t nExponent,
3883 uint64_t *puResult,
3884 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003885{
3886 if(nMantissa < 0) {
3887 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3888 }
3889
3890 // Cast to unsigned is OK because of check for negative
3891 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3892 // Exponentiation is straight forward
3893 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3894}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003895
3896
3897/*
3898 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3899 */
3900static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3901 int64_t nExponent,
3902 uint64_t *puResult,
3903 fExponentiator pfExp)
3904{
3905 return (*pfExp)(uMantissa, nExponent, puResult);
3906}
3907
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003908#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3909
3910
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003911
3912
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003913
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003914static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003915{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003916 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003918 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003919 const uint8_t *pByte = BigNum.ptr;
3920 size_t uLen = BigNum.len;
3921 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003922 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003923 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003924 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003925 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003926 }
3927
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003928 *pResult = uResult;
3929 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003930}
3931
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003932
Laurence Lundblade887add82020-05-17 05:50:34 -07003933static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003934{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003935 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936}
3937
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003938
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003939static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003940{
3941 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003942 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3943 if(uError) {
3944 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003945 }
3946 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3947 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003948 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003949}
3950
3951
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003952static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003953{
3954 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003955 /* The negative integer furthest from zero for a C int64_t is
3956 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3957 negative number in CBOR is computed as -n - 1 where n is the
3958 encoded integer, where n is what is in the variable BigNum. When
3959 converting BigNum to a uint64_t, the maximum value is thus
3960 INT64_MAX, so that when it -n - 1 is applied to it the result will
3961 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003962
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003963 -n - 1 <= INT64_MIN.
3964 -n - 1 <= -INT64_MAX - 1
3965 n <= INT64_MAX.
3966 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003967 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003968 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003969 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003970 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003971
3972 /// Now apply -n - 1. The cast is safe because
3973 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3974 // is the largest positive integer that an int64_t can
3975 // represent. */
3976 *pnResult = -(int64_t)uResult - 1;
3977
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003978 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003979}
3980
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003981
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003982
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003983
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003984
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003985/*
3986Convert a integers and floats to an int64_t.
3987
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003988\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003989
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003990\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003991
3992\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3993
3994\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3995
3996*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003997static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003998{
3999 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004000 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004001 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004002#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004003 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004004 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4005 http://www.cplusplus.com/reference/cmath/llround/
4006 */
4007 // Not interested in FE_INEXACT
4008 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004009 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4010 *pnValue = llround(pItem->val.dfnum);
4011 } else {
4012 *pnValue = lroundf(pItem->val.fnum);
4013 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004014 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4015 // llround() shouldn't result in divide by zero, but catch
4016 // it here in case it unexpectedly does. Don't try to
4017 // distinguish between the various exceptions because it seems
4018 // they vary by CPU, compiler and OS.
4019 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004020 }
4021 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004024#else
4025 return QCBOR_ERR_HW_FLOAT_DISABLED;
4026#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004027 break;
4028
4029 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004030 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004031 *pnValue = pItem->val.int64;
4032 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004033 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004034 }
4035 break;
4036
4037 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004039 if(pItem->val.uint64 < INT64_MAX) {
4040 *pnValue = pItem->val.int64;
4041 } else {
4042 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4043 }
4044 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004045 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004046 }
4047 break;
4048
4049 default:
4050 return QCBOR_ERR_UNEXPECTED_TYPE;
4051 }
4052 return QCBOR_SUCCESS;
4053}
4054
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004055
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004056void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004058 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004059 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004060{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004061 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004062 return;
4063 }
4064
Laurence Lundbladee6430642020-03-14 21:15:44 -07004065 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004066 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4067 if(uError) {
4068 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004069 return;
4070 }
4071
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004072 if(pItem) {
4073 *pItem = Item;
4074 }
4075
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004076 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077}
4078
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004079
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004080void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4081 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004082 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004083 int64_t *pnValue,
4084 QCBORItem *pItem)
4085{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004086 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004087 if(pMe->uLastError != QCBOR_SUCCESS) {
4088 return;
4089 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004091 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004092}
4093
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004094
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4096 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004097 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004098 int64_t *pnValue,
4099 QCBORItem *pItem)
4100{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004101 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004102 if(pMe->uLastError != QCBOR_SUCCESS) {
4103 return;
4104 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004105
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107}
4108
4109
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004110/*
4111 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004113 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004114
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004116
4117 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4118
4119 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4120
4121 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004124 switch(pItem->uDataType) {
4125
4126 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004128 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004129 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004130 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004131 }
4132 break;
4133
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004134 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004135 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004137 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004138 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004139 }
4140 break;
4141
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004142#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4143 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004145 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004146 pItem->val.expAndMantissa.nExponent,
4147 pnValue,
4148 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004149 } 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
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004154 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004156 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004157 pItem->val.expAndMantissa.nExponent,
4158 pnValue,
4159 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004161 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004162 }
4163 break;
4164
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004165 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004167 int64_t nMantissa;
4168 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004169 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4170 if(uErr) {
4171 return uErr;
4172 }
4173 return ExponentiateNN(nMantissa,
4174 pItem->val.expAndMantissa.nExponent,
4175 pnValue,
4176 Exponentitate10);
4177 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004178 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004179 }
4180 break;
4181
4182 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004183 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004184 int64_t nMantissa;
4185 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4187 if(uErr) {
4188 return uErr;
4189 }
4190 return ExponentiateNN(nMantissa,
4191 pItem->val.expAndMantissa.nExponent,
4192 pnValue,
4193 Exponentitate10);
4194 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004195 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004196 }
4197 break;
4198
4199 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004201 int64_t nMantissa;
4202 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004203 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4204 if(uErr) {
4205 return uErr;
4206 }
4207 return ExponentiateNN(nMantissa,
4208 pItem->val.expAndMantissa.nExponent,
4209 pnValue,
4210 Exponentitate2);
4211 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004212 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213 }
4214 break;
4215
4216 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004217 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004218 int64_t nMantissa;
4219 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004220 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4221 if(uErr) {
4222 return uErr;
4223 }
4224 return ExponentiateNN(nMantissa,
4225 pItem->val.expAndMantissa.nExponent,
4226 pnValue,
4227 Exponentitate2);
4228 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004229 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004230 }
4231 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004232#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4233
Laurence Lundbladee6430642020-03-14 21:15:44 -07004234
Laurence Lundbladec4537442020-04-14 18:53:22 -07004235 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004236 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004237}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004238
4239
Laurence Lundbladec4537442020-04-14 18:53:22 -07004240/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004241 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004242 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004244{
4245 QCBORItem Item;
4246
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004247 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004248
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004249 if(pMe->uLastError == QCBOR_SUCCESS) {
4250 // The above conversion succeeded
4251 return;
4252 }
4253
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004254 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004255 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004256 return;
4257 }
4258
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004259 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004260}
4261
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004262
4263/*
4264Public function, see header qcbor/qcbor_decode.h file
4265*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004266void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4267 int64_t nLabel,
4268 uint32_t uConvertTypes,
4269 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004270{
4271 QCBORItem Item;
4272
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004273 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004274
4275 if(pMe->uLastError == QCBOR_SUCCESS) {
4276 // The above conversion succeeded
4277 return;
4278 }
4279
4280 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4281 // The above conversion failed in a way that code below can't correct
4282 return;
4283 }
4284
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004285 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004286}
4287
4288
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004289/*
4290Public function, see header qcbor/qcbor_decode.h file
4291*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004292void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4293 const char *szLabel,
4294 uint32_t uConvertTypes,
4295 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004296{
4297 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004298 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004299
4300 if(pMe->uLastError == QCBOR_SUCCESS) {
4301 // The above conversion succeeded
4302 return;
4303 }
4304
4305 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4306 // The above conversion failed in a way that code below can't correct
4307 return;
4308 }
4309
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004310 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004311}
4312
4313
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004314static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004315{
4316 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004317 case QCBOR_TYPE_DOUBLE:
4318 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004319#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004320 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004321 // Can't use llround here because it will not convert values
4322 // greater than INT64_MAX and less than UINT64_MAX that
4323 // need to be converted so it is more complicated.
4324 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4325 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4326 if(isnan(pItem->val.dfnum)) {
4327 return QCBOR_ERR_FLOAT_EXCEPTION;
4328 } else if(pItem->val.dfnum < 0) {
4329 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4330 } else {
4331 double dRounded = round(pItem->val.dfnum);
4332 // See discussion in DecodeDateEpoch() for
4333 // explanation of - 0x7ff
4334 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4335 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4336 }
4337 *puValue = (uint64_t)dRounded;
4338 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004339 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004340 if(isnan(pItem->val.fnum)) {
4341 return QCBOR_ERR_FLOAT_EXCEPTION;
4342 } else if(pItem->val.fnum < 0) {
4343 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4344 } else {
4345 float fRounded = roundf(pItem->val.fnum);
4346 // See discussion in DecodeDateEpoch() for
4347 // explanation of - 0x7ff
4348 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4349 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4350 }
4351 *puValue = (uint64_t)fRounded;
4352 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004353 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004354 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4355 // round() and roundf() shouldn't result in exceptions here, but
4356 // catch them to be robust and thorough. Don't try to
4357 // distinguish between the various exceptions because it seems
4358 // they vary by CPU, compiler and OS.
4359 return QCBOR_ERR_FLOAT_EXCEPTION;
4360 }
4361
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004362 } else {
4363 return QCBOR_ERR_UNEXPECTED_TYPE;
4364 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004365#else
4366 return QCBOR_ERR_HW_FLOAT_DISABLED;
4367#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004368 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004369
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004370 case QCBOR_TYPE_INT64:
4371 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4372 if(pItem->val.int64 >= 0) {
4373 *puValue = (uint64_t)pItem->val.int64;
4374 } else {
4375 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4376 }
4377 } else {
4378 return QCBOR_ERR_UNEXPECTED_TYPE;
4379 }
4380 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004381
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004382 case QCBOR_TYPE_UINT64:
4383 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4384 *puValue = pItem->val.uint64;
4385 } else {
4386 return QCBOR_ERR_UNEXPECTED_TYPE;
4387 }
4388 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004390 default:
4391 return QCBOR_ERR_UNEXPECTED_TYPE;
4392 }
4393
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004394 return QCBOR_SUCCESS;
4395}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004396
4397
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004398void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004399 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004401 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004402{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004403 if(pMe->uLastError != QCBOR_SUCCESS) {
4404 return;
4405 }
4406
Laurence Lundbladec4537442020-04-14 18:53:22 -07004407 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004408
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004409 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4410 if(uError) {
4411 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004412 return;
4413 }
4414
Laurence Lundbladea826c502020-05-10 21:07:00 -07004415 if(pItem) {
4416 *pItem = Item;
4417 }
4418
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004419 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004420}
4421
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004422
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004423void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426 uint64_t *puValue,
4427 QCBORItem *pItem)
4428{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004429 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004430 if(pMe->uLastError != QCBOR_SUCCESS) {
4431 return;
4432 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004433
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004434 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435}
4436
4437
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004438void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004439 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004440 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441 uint64_t *puValue,
4442 QCBORItem *pItem)
4443{
4444 if(pMe->uLastError != QCBOR_SUCCESS) {
4445 return;
4446 }
4447
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004448 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004449 if(pMe->uLastError != QCBOR_SUCCESS) {
4450 return;
4451 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004453 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454}
4455
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004456
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004457/*
4458 Public function, see header qcbor/qcbor_decode.h file
4459*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004460static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004461{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 switch(pItem->uDataType) {
4463
4464 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004465 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004466 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4467 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004468 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469 }
4470 break;
4471
4472 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004473 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4475 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004476 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004477 }
4478 break;
4479
4480#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4481
4482 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004485 pItem->val.expAndMantissa.nExponent,
4486 puValue,
4487 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488 } 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_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004494 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4496 pItem->val.expAndMantissa.nExponent,
4497 puValue,
4498 Exponentitate2);
4499 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004500 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 }
4502 break;
4503
4504 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004506 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004507 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004508 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509 if(uErr != QCBOR_SUCCESS) {
4510 return uErr;
4511 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004512 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004513 pItem->val.expAndMantissa.nExponent,
4514 puValue,
4515 Exponentitate10);
4516 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004517 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004518 }
4519 break;
4520
4521 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004522 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4524 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004525 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526 }
4527 break;
4528
4529 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004530 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004531 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004532 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004533 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 if(uErr != QCBOR_SUCCESS) {
4535 return uErr;
4536 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004537 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004538 pItem->val.expAndMantissa.nExponent,
4539 puValue,
4540 Exponentitate2);
4541 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004542 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004543 }
4544 break;
4545
4546 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004547 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4549 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004550 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004551 }
4552 break;
4553#endif
4554 default:
4555 return QCBOR_ERR_UNEXPECTED_TYPE;
4556 }
4557}
4558
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004559
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004560/*
4561 Public function, see header qcbor/qcbor_decode.h file
4562*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004564{
4565 QCBORItem Item;
4566
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004567 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004568
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004569 if(pMe->uLastError == QCBOR_SUCCESS) {
4570 // The above conversion succeeded
4571 return;
4572 }
4573
4574 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4575 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004576 return;
4577 }
4578
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004579 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004580}
4581
Laurence Lundbladec4537442020-04-14 18:53:22 -07004582
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004584 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004585*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004586void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004587 int64_t nLabel,
4588 uint32_t uConvertTypes,
4589 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004590{
4591 QCBORItem Item;
4592
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004593 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004594
4595 if(pMe->uLastError == QCBOR_SUCCESS) {
4596 // The above conversion succeeded
4597 return;
4598 }
4599
4600 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4601 // The above conversion failed in a way that code below can't correct
4602 return;
4603 }
4604
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004605 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004606}
4607
4608
4609/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004610 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004611*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004612void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004613 const char *szLabel,
4614 uint32_t uConvertTypes,
4615 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616{
4617 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004618 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004619
4620 if(pMe->uLastError == QCBOR_SUCCESS) {
4621 // The above conversion succeeded
4622 return;
4623 }
4624
4625 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4626 // The above conversion failed in a way that code below can't correct
4627 return;
4628 }
4629
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004630 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631}
4632
4633
Laurence Lundblade9b334962020-08-27 10:55:53 -07004634static QCBORError ConvertDouble(const QCBORItem *pItem,
4635 uint32_t uConvertTypes,
4636 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637{
4638 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004639 case QCBOR_TYPE_FLOAT:
4640#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4641 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4642 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004643 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004644 *pdValue = (double)pItem->val.fnum;
4645 } else {
4646 return QCBOR_ERR_UNEXPECTED_TYPE;
4647 }
4648 }
4649#else
4650 return QCBOR_ERR_HW_FLOAT_DISABLED;
4651#endif
4652 break;
4653
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004654 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004655 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4656 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657 *pdValue = pItem->val.dfnum;
4658 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004659 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660 }
4661 }
4662 break;
4663
4664 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004665#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004667 // A simple cast seems to do the job with no worry of exceptions.
4668 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004669 *pdValue = (double)pItem->val.int64;
4670
4671 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004672 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004673 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004674#else
4675 return QCBOR_ERR_HW_FLOAT_DISABLED;
4676#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677 break;
4678
4679 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004680#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004682 // A simple cast seems to do the job with no worry of exceptions.
4683 // There will be precision loss for some values.
4684 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004686 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004687 }
4688 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004689#else
4690 return QCBOR_ERR_HW_FLOAT_DISABLED;
4691#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692
4693 default:
4694 return QCBOR_ERR_UNEXPECTED_TYPE;
4695 }
4696
4697 return QCBOR_SUCCESS;
4698}
4699
4700
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004701void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004702 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004703 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004704 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004705{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004706 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004707 return;
4708 }
4709
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004710 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004711
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004712 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004713 if(uError) {
4714 pMe->uLastError = (uint8_t)uError;
4715 return;
4716 }
4717
4718 if(pItem) {
4719 *pItem = Item;
4720 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004721
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004722 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004723}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004724
Laurence Lundbladec4537442020-04-14 18:53:22 -07004725
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4727 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004728 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729 double *pdValue,
4730 QCBORItem *pItem)
4731{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004732 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004733 if(pMe->uLastError != QCBOR_SUCCESS) {
4734 return;
4735 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004736
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004738}
4739
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004740
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4742 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004743 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004744 double *pdValue,
4745 QCBORItem *pItem)
4746{
4747 if(pMe->uLastError != QCBOR_SUCCESS) {
4748 return;
4749 }
4750
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004751 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004752 if(pMe->uLastError != QCBOR_SUCCESS) {
4753 return;
4754 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004755
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757}
4758
4759
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004760#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004761static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4762{
4763 double dResult;
4764
4765 dResult = 0.0;
4766 const uint8_t *pByte = BigNum.ptr;
4767 size_t uLen = BigNum.len;
4768 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004769 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004770 while(uLen--) {
4771 dResult = (dResult * 256.0) + (double)*pByte++;
4772 }
4773
4774 return dResult;
4775}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004776#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4777
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004778
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004780{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004781#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004782 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004783 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4784
4785 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004787
4788#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004790 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004791 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4793 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4794 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004795 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004796 }
4797 break;
4798
4799 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004801 // Underflow gives 0, overflow gives infinity
4802 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4803 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004804 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004805 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 }
4807 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004808#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004809
4810 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004812 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4813 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004814 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004815 }
4816 break;
4817
4818 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004819 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004820 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004821 } 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
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004826#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004828 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4830 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4831 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 }
4834 break;
4835
4836 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004837 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004838 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4839 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4840 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 }
4843 break;
4844
4845 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004846 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4848 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4849 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004850 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004851 }
4852 break;
4853
4854 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004855 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004856 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004857 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4858 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860 }
4861 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004862#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4863
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004864 default:
4865 return QCBOR_ERR_UNEXPECTED_TYPE;
4866 }
4867
4868 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004869
4870#else
4871 (void)pItem;
4872 (void)uConvertTypes;
4873 (void)pdValue;
4874 return QCBOR_ERR_HW_FLOAT_DISABLED;
4875#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4876
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877}
4878
4879
4880/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004881 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004883void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4884 uint32_t uConvertTypes,
4885 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886{
4887
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004888 QCBORItem Item;
4889
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004890 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004891
4892 if(pMe->uLastError == QCBOR_SUCCESS) {
4893 // The above conversion succeeded
4894 return;
4895 }
4896
4897 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4898 // The above conversion failed in a way that code below can't correct
4899 return;
4900 }
4901
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004902 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004903}
4904
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905
4906/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004907 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004908*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004909void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4910 int64_t nLabel,
4911 uint32_t uConvertTypes,
4912 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004913{
4914 QCBORItem Item;
4915
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004916 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004917
4918 if(pMe->uLastError == QCBOR_SUCCESS) {
4919 // The above conversion succeeded
4920 return;
4921 }
4922
4923 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4924 // The above conversion failed in a way that code below can't correct
4925 return;
4926 }
4927
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004928 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004929}
4930
4931
4932/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004933 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004934*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004935void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4936 const char *szLabel,
4937 uint32_t uConvertTypes,
4938 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939{
4940 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004941 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004942
4943 if(pMe->uLastError == QCBOR_SUCCESS) {
4944 // The above conversion succeeded
4945 return;
4946 }
4947
4948 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4949 // The above conversion failed in a way that code below can't correct
4950 return;
4951 }
4952
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004953 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004954}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004955
4956
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004957
4958
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004959#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004960static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4961{
4962 while((uInt & 0xff00000000000000UL) == 0) {
4963 uInt = uInt << 8;
4964 };
4965
4966 UsefulOutBuf UOB;
4967
4968 UsefulOutBuf_Init(&UOB, Buffer);
4969
4970 while(uInt) {
4971 const uint64_t xx = uInt & 0xff00000000000000UL;
4972 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4973 uInt = uInt << 8;
4974 (void)xx;
4975 }
4976
4977 return UsefulOutBuf_OutUBuf(&UOB);
4978}
4979
4980
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004981static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4982 TagSpecification TagSpec,
4983 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004984{
4985 QCBORError uErr;
4986 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004987 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004988 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004989 if(uErr != QCBOR_SUCCESS) {
4990 goto Done;
4991 }
4992
4993 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4994 break; // Successful exit. Moving on to finish decoding.
4995 }
4996
4997 // The item is an array, which means an undecoded
4998 // mantissa and exponent, so decode it. It will then
4999 // have a different type and exit the loop if.
5000 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5001 if(uErr != QCBOR_SUCCESS) {
5002 goto Done;
5003 }
5004
5005 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005006 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005007 }
5008Done:
5009 return uErr;
5010}
5011
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005012
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005013static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005014 TagSpecification TagSpec,
5015 QCBORItem *pItem,
5016 int64_t *pnMantissa,
5017 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005018{
5019 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005020
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005021 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005022 if(uErr != QCBOR_SUCCESS) {
5023 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005024 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005025
Laurence Lundblade9b334962020-08-27 10:55:53 -07005026 switch (pItem->uDataType) {
5027
5028 case QCBOR_TYPE_DECIMAL_FRACTION:
5029 case QCBOR_TYPE_BIGFLOAT:
5030 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5031 *pnExponent = pItem->val.expAndMantissa.nExponent;
5032 break;
5033
5034 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5035 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5036 *pnExponent = pItem->val.expAndMantissa.nExponent;
5037 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5038 break;
5039
5040 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5041 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5042 *pnExponent = pItem->val.expAndMantissa.nExponent;
5043 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5044 break;
5045
5046 default:
5047 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5048 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005049
5050 Done:
5051 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005052}
5053
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005054
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005055static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005056 TagSpecification TagSpec,
5057 QCBORItem *pItem,
5058 UsefulBuf BufferForMantissa,
5059 UsefulBufC *pMantissa,
5060 bool *pbIsNegative,
5061 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005062{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005063 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005064
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005065 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005066 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005067 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005068 }
5069
5070 uint64_t uMantissa;
5071
5072 switch (pItem->uDataType) {
5073
5074 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005075 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005076 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5077 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5078 *pbIsNegative = false;
5079 } else {
5080 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5081 *pbIsNegative = true;
5082 }
5083 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5084 *pnExponent = pItem->val.expAndMantissa.nExponent;
5085 break;
5086
5087 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005088 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005089 *pnExponent = pItem->val.expAndMantissa.nExponent;
5090 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5091 *pbIsNegative = false;
5092 break;
5093
5094 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005095 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005096 *pnExponent = pItem->val.expAndMantissa.nExponent;
5097 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5098 *pbIsNegative = true;
5099 break;
5100
5101 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005102 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005103 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005104
5105Done:
5106 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005107}
5108
5109
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005110/*
5111 Public function, see header qcbor/qcbor_decode.h file
5112*/
5113void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5114 uint8_t uTagRequirement,
5115 int64_t *pnMantissa,
5116 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005117{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005118 if(pMe->uLastError != QCBOR_SUCCESS) {
5119 return;
5120 }
5121
5122 QCBORItem Item;
5123 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5124 if(uError) {
5125 pMe->uLastError = (uint8_t)uError;
5126 return;
5127 }
5128
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005129 const TagSpecification TagSpec =
5130 {
5131 uTagRequirement,
5132 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5133 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5134 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005135
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005136 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005137}
5138
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005139
5140/*
5141 Public function, see header qcbor/qcbor_decode.h file
5142*/
5143void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005145 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005146 int64_t *pnMantissa,
5147 int64_t *pnExponent)
5148{
5149 if(pMe->uLastError != QCBOR_SUCCESS) {
5150 return;
5151 }
5152
5153 QCBORItem Item;
5154 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5155
5156 const TagSpecification TagSpec =
5157 {
5158 uTagRequirement,
5159 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5160 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5161 };
5162
5163 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5164}
5165
5166
5167/*
5168 Public function, see header qcbor/qcbor_decode.h file
5169*/
5170void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005171 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005172 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005173 int64_t *pnMantissa,
5174 int64_t *pnExponent)
5175{
5176 if(pMe->uLastError != QCBOR_SUCCESS) {
5177 return;
5178 }
5179
5180 QCBORItem Item;
5181 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5182
5183 const TagSpecification TagSpec =
5184 {
5185 uTagRequirement,
5186 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5187 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5188 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005189
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5191}
5192
5193
5194/*
5195 Public function, see header qcbor/qcbor_decode.h file
5196*/
5197void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5198 uint8_t uTagRequirement,
5199 UsefulBuf MantissaBuffer,
5200 UsefulBufC *pMantissa,
5201 bool *pbMantissaIsNegative,
5202 int64_t *pnExponent)
5203{
5204 if(pMe->uLastError != QCBOR_SUCCESS) {
5205 return;
5206 }
5207
5208 QCBORItem Item;
5209 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5210 if(uError) {
5211 pMe->uLastError = (uint8_t)uError;
5212 return;
5213 }
5214
5215 const TagSpecification TagSpec =
5216 {
5217 uTagRequirement,
5218 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5219 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5220 };
5221
5222 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5223}
5224
5225
5226/*
5227 Public function, see header qcbor/qcbor_decode.h file
5228*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005229void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005230 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005231 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005232 UsefulBuf BufferForMantissa,
5233 UsefulBufC *pMantissa,
5234 bool *pbIsNegative,
5235 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005236{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005237 if(pMe->uLastError != QCBOR_SUCCESS) {
5238 return;
5239 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005240
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005241 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005242 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005243 if(pMe->uLastError != QCBOR_SUCCESS) {
5244 return;
5245 }
5246
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005247 const TagSpecification TagSpec =
5248 {
5249 uTagRequirement,
5250 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5251 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5252 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005253
5254 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005255}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005256
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005257
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005258/*
5259 Public function, see header qcbor/qcbor_decode.h file
5260*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005261void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005262 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005263 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005264 UsefulBuf BufferForMantissa,
5265 UsefulBufC *pMantissa,
5266 bool *pbIsNegative,
5267 int64_t *pnExponent)
5268{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005269 if(pMe->uLastError != QCBOR_SUCCESS) {
5270 return;
5271 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005272
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005273 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005274 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5275 if(pMe->uLastError != QCBOR_SUCCESS) {
5276 return;
5277 }
5278
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005279 const TagSpecification TagSpec =
5280 {
5281 uTagRequirement,
5282 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5283 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5284 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005285
5286 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5287}
5288
5289
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005290/*
5291 Public function, see header qcbor/qcbor_decode.h file
5292*/
5293void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5294 uint8_t uTagRequirement,
5295 int64_t *pnMantissa,
5296 int64_t *pnExponent)
5297{
5298 if(pMe->uLastError != QCBOR_SUCCESS) {
5299 return;
5300 }
5301
5302 QCBORItem Item;
5303 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5304 if(uError) {
5305 pMe->uLastError = (uint8_t)uError;
5306 return;
5307 }
5308 const TagSpecification TagSpec =
5309 {
5310 uTagRequirement,
5311 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5312 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5313 };
5314
5315 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5316}
5317
5318
5319/*
5320 Public function, see header qcbor/qcbor_decode.h file
5321*/
5322void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005323 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005324 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005325 int64_t *pnMantissa,
5326 int64_t *pnExponent)
5327{
5328 if(pMe->uLastError != QCBOR_SUCCESS) {
5329 return;
5330 }
5331
5332 QCBORItem Item;
5333 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5334 if(pMe->uLastError != QCBOR_SUCCESS) {
5335 return;
5336 }
5337
5338 const TagSpecification TagSpec =
5339 {
5340 uTagRequirement,
5341 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5342 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5343 };
5344
5345 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5346}
5347
5348
5349/*
5350 Public function, see header qcbor/qcbor_decode.h file
5351*/
5352void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005353 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005354 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005355 int64_t *pnMantissa,
5356 int64_t *pnExponent)
5357{
5358 if(pMe->uLastError != QCBOR_SUCCESS) {
5359 return;
5360 }
5361
5362 QCBORItem Item;
5363 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5364 if(pMe->uLastError != QCBOR_SUCCESS) {
5365 return;
5366 }
5367
5368 const TagSpecification TagSpec =
5369 {
5370 uTagRequirement,
5371 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5372 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5373 };
5374
5375 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5376}
5377
5378
5379/*
5380 Public function, see header qcbor/qcbor_decode.h file
5381*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005382void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5383 uint8_t uTagRequirement,
5384 UsefulBuf MantissaBuffer,
5385 UsefulBufC *pMantissa,
5386 bool *pbMantissaIsNegative,
5387 int64_t *pnExponent)
5388{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005389 if(pMe->uLastError != QCBOR_SUCCESS) {
5390 return;
5391 }
5392
5393 QCBORItem Item;
5394 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5395 if(uError) {
5396 pMe->uLastError = (uint8_t)uError;
5397 return;
5398 }
5399
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005400 const TagSpecification TagSpec =
5401 {
5402 uTagRequirement,
5403 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5404 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5405 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005406
5407 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005408}
5409
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005410
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005411/*
5412 Public function, see header qcbor/qcbor_decode.h file
5413*/
5414void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005416 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005417 UsefulBuf BufferForMantissa,
5418 UsefulBufC *pMantissa,
5419 bool *pbIsNegative,
5420 int64_t *pnExponent)
5421{
5422 if(pMe->uLastError != QCBOR_SUCCESS) {
5423 return;
5424 }
5425
5426 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005427 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5428 if(pMe->uLastError != QCBOR_SUCCESS) {
5429 return;
5430 }
5431
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005432 const TagSpecification TagSpec =
5433 {
5434 uTagRequirement,
5435 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5436 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5437 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005438
5439 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5440}
5441
5442
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005443/*
5444 Public function, see header qcbor/qcbor_decode.h file
5445*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005447 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005448 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005449 UsefulBuf BufferForMantissa,
5450 UsefulBufC *pMantissa,
5451 bool *pbIsNegative,
5452 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005453{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005454 if(pMe->uLastError != QCBOR_SUCCESS) {
5455 return;
5456 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005457
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005458 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005459 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5460 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005461 return;
5462 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005463
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005464 const TagSpecification TagSpec =
5465 {
5466 uTagRequirement,
5467 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5468 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5469 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005470
5471 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005472}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005473
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005474#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */