blob: 736db6c24cbfcc7c5aef8db59b72c39cade16b78 [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 Lundbladeb69cad72018-09-13 11:09:01 -0700474
Laurence Lundbladeee851742020-01-08 08:37:05 -0800475/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800476 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
477
478 The following four functions are pretty wrappers for invocation of
479 the string allocator supplied by the caller.
480
Laurence Lundbladeee851742020-01-08 08:37:05 -0800481 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800482
Laurence Lundbladeee851742020-01-08 08:37:05 -0800483static inline void
484StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485{
486 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
487}
488
Laurence Lundbladeee851742020-01-08 08:37:05 -0800489// StringAllocator_Reallocate called with pMem NULL is
490// equal to StringAllocator_Allocate()
491static inline UsefulBuf
492StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
493 void *pMem,
494 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800495{
496 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
497}
498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499static inline UsefulBuf
500StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800501{
502 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
503}
504
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505static inline void
506StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800507{
508 if(pMe->pfAllocator) {
509 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
510 }
511}
512
513
514
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515/*===========================================================================
516 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800518 See qcbor/qcbor_decode.h for definition of the object
519 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800520 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700521/*
522 Public function, see header file
523 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800524void QCBORDecode_Init(QCBORDecodeContext *me,
525 UsefulBufC EncodedCBOR,
526 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527{
528 memset(me, 0, sizeof(QCBORDecodeContext));
529 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800530 // Don't bother with error check on decode mode. If a bad value is
531 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700532 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700533 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700534 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700535 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700536 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700537}
538
539
540/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700541 Public function, see header file
542 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
544 QCBORStringAllocate pfAllocateFunction,
545 void *pAllocateContext,
546 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700547{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800548 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
549 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
550 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700551}
552
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800553
554/*
555 Public function, see header file
556 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700557void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800558 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700559{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700560 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700561 (void)pMe;
562 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700563}
564
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700565
566/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567 This decodes the fundamental part of a CBOR data item, the type and
568 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800569
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700570 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800571
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572 This does the network->host byte order conversion. The conversion
573 here also results in the conversion for floats in addition to that
574 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800575
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700576 This returns:
577 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800578
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800579 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800580 tags and floats and length for strings and arrays
581
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800582 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800583 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800584
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585 The int type is preferred to uint8_t for some variables as this
586 avoids integer promotions, can reduce code size and makes
587 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700588
589 @retval QCBOR_ERR_UNSUPPORTED
590
591 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800593inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
594 int *pnMajorType,
595 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800596 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700598 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800599
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800601 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800602
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800604 const int nTmpMajorType = nInitialByte >> 5;
605 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800607 // Where the number or argument accumulates
608 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800610 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700611 // Need to get 1,2,4 or 8 additional argument bytes. Map
612 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800613 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800614
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800615 // Loop getting all the bytes in the argument
616 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800617 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618 // This shift and add gives the endian conversion
619 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
620 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800622 // The reserved and thus-far unused additional info values
623 nReturn = QCBOR_ERR_UNSUPPORTED;
624 goto Done;
625 } else {
626 // Less than 24, additional info is argument or 31, an indefinite length
627 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 if(UsefulInputBuf_GetError(pUInBuf)) {
632 nReturn = QCBOR_ERR_HIT_END;
633 goto Done;
634 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800635
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700636 // All successful if we got here.
637 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800639 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800641
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642Done:
643 return nReturn;
644}
645
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800648 CBOR doesn't explicitly specify two's compliment for integers but all
649 CPUs use it these days and the test vectors in the RFC are so. All
650 integers in the CBOR structure are positive and the major type
651 indicates positive or negative. CBOR can express positive integers
652 up to 2^x - 1 where x is the number of bits and negative integers
653 down to 2^x. Note that negative numbers can be one more away from
654 zero than positive. Stdint, as far as I can tell, uses two's
655 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800656
Laurence Lundblade9b334962020-08-27 10:55:53 -0700657 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 used carefully here, and in particular why it isn't used in the interface.
659 Also see
660 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
661
662 Int is used for values that need less than 16-bits and would be subject
663 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700664
665 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800667inline static QCBORError
668DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700670 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
673 if (uNumber <= INT64_MAX) {
674 pDecodedItem->val.int64 = (int64_t)uNumber;
675 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677 } else {
678 pDecodedItem->val.uint64 = uNumber;
679 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681 }
682 } else {
683 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684 // CBOR's representation of negative numbers lines up with the
685 // two-compliment representation. A negative integer has one
686 // more in range than a positive integer. INT64_MIN is
687 // equal to (-INT64_MAX) - 1.
688 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 } else {
692 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000693 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 nReturn = QCBOR_ERR_INT_OVERFLOW;
695 }
696 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698 return nReturn;
699}
700
701// Make sure #define value line up as DecodeSimple counts on this.
702#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
703#error QCBOR_TYPE_FALSE macro value wrong
704#endif
705
706#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
707#error QCBOR_TYPE_TRUE macro value wrong
708#endif
709
710#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
711#error QCBOR_TYPE_NULL macro value wrong
712#endif
713
714#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
715#error QCBOR_TYPE_UNDEF macro value wrong
716#endif
717
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700718#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
719#error QCBOR_TYPE_BREAK macro value wrong
720#endif
721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
723#error QCBOR_TYPE_DOUBLE macro value wrong
724#endif
725
726#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
727#error QCBOR_TYPE_FLOAT macro value wrong
728#endif
729
730/*
731 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700732
733 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
734
735 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800737inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700740 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700742 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800743 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700744 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800745 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800746
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800748 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
749 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800750
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700751 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700752#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700753 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700754 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700755 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700756 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
757 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700758#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700759 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700760#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700761 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700763 // Single precision is normally returned as a double
764 // since double is widely supported, there is no loss of
765 // precision, it makes it easy for the caller in
766 // most cases and it can be converted back to single
767 // with no loss of precision
768 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700769 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700770 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700771 {
772 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
773#ifndef QCBOR_DISABLE_FLOAT_HW_USE
774 // In the normal case, use HW to convert float to double.
775 pDecodedItem->val.dfnum = (double)f;
776 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700777#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700778 // Use of float HW is disabled, return as a float.
779 pDecodedItem->val.fnum = f;
780 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
781
782 // IEEE754_FloatToDouble() could be used here to return
783 // as a double, but it adds object code and most likely
784 // anyone disabling FLOAT HW use doesn't care about
785 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700786#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700787 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700788 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700790 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700792 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700793 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 case CBOR_SIMPLEV_FALSE: // 20
796 case CBOR_SIMPLEV_TRUE: // 21
797 case CBOR_SIMPLEV_NULL: // 22
798 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700799 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802 case CBOR_SIMPLEV_ONEBYTE: // 24
803 if(uNumber <= CBOR_SIMPLE_BREAK) {
804 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700805 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 goto Done;
807 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800808 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 default: // 0-19
812 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 /*
814 DecodeTypeAndNumber will make uNumber equal to
815 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
816 safe because the 2, 4 and 8 byte lengths of uNumber are in
817 the double/float cases above
818 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 pDecodedItem->val.uSimple = (uint8_t)uNumber;
820 break;
821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823Done:
824 return nReturn;
825}
826
827
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530829 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700830
831 @retval QCBOR_ERR_HIT_END
832
833 @retval QCBOR_ERR_STRING_ALLOCATE
834
835 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800837inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
838 int nMajorType,
839 uint64_t uStrLen,
840 UsefulInputBuf *pUInBuf,
841 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700843 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800844
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800845 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
846 // This check makes the casts to size_t below safe.
847
848 // 4 bytes less than the largest sizeof() so this can be tested by
849 // putting a SIZE_MAX length in the CBOR test input (no one will
850 // care the limit on strings is 4 bytes shorter).
851 if(uStrLen > SIZE_MAX-4) {
852 nReturn = QCBOR_ERR_STRING_TOO_LONG;
853 goto Done;
854 }
855
856 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530857 if(UsefulBuf_IsNULLC(Bytes)) {
858 // Failed to get the bytes for this string item
859 nReturn = QCBOR_ERR_HIT_END;
860 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530862
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800863 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530864 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800865 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530866 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700867 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530868 goto Done;
869 }
870 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800871 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872 } else {
873 // Normal case with no string allocator
874 pDecodedItem->val.string = Bytes;
875 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800876 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800877 // Cast because ternary operator causes promotion to integer
878 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
879 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800880
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530881Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 return nReturn;
883}
884
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887
888
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889
890
Laurence Lundbladeee851742020-01-08 08:37:05 -0800891// Make sure the constants align as this is assumed by
892// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
894#error QCBOR_TYPE_ARRAY value not lined up with major type
895#endif
896#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
897#error QCBOR_TYPE_MAP value not lined up with major type
898#endif
899
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901 This gets a single data item and decodes it including preceding
902 optional tagging. This does not deal with arrays and maps and nesting
903 except to decode the data item introducing them. Arrays and maps are
904 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladeee851742020-01-08 08:37:05 -0800906 Errors detected here include: an array that is too long to decode,
907 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700908
909 @retval QCBOR_ERR_UNSUPPORTED
910
911 @retval QCBOR_ERR_HIT_END
912
913 @retval QCBOR_ERR_INT_OVERFLOW
914
915 @retval QCBOR_ERR_STRING_ALLOCATE
916
917 @retval QCBOR_ERR_STRING_TOO_LONG
918
919 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
920
921 @retval QCBOR_ERR_BAD_TYPE_7
922
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800924static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
925 QCBORItem *pDecodedItem,
926 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700928 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundbladeee851742020-01-08 08:37:05 -0800930 /*
931 Get the major type and the number. Number could be length of more
932 bytes or the value depending on the major type nAdditionalInfo is
933 an encoding of the length of the uNumber and is needed to decode
934 floats and doubles
935 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800936 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800938 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700940 memset(pDecodedItem, 0, sizeof(QCBORItem));
941
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800942 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundbladeee851742020-01-08 08:37:05 -0800944 // Error out here if we got into trouble on the type and number. The
945 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700946 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700947 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundbladeee851742020-01-08 08:37:05 -0800950 // At this point the major type and the value are valid. We've got
951 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800952 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
954 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700956 nReturn = QCBOR_ERR_BAD_INT;
957 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700959 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
963 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
965 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
966 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
967 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530968 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800970 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700971 }
972 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
975 case CBOR_MAJOR_TYPE_MAP: // Major type 5
976 // Record the number of items in the array or map
977 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700978 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 goto Done;
980 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800981 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700982 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800984 // type conversion OK because of check above
985 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
989 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800993 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700994 nReturn = QCBOR_ERR_BAD_INT;
995 } else {
996 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -0700997 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700998 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 case CBOR_MAJOR_TYPE_SIMPLE:
1002 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001003 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001005
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 default:
1007 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 nReturn = QCBOR_ERR_UNSUPPORTED;
1009 break;
1010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012Done:
1013 return nReturn;
1014}
1015
1016
1017
1018/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001019 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 individual chunk items together into one QCBORItem using the string
1021 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301023 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001024
1025 @retval QCBOR_ERR_UNSUPPORTED
1026
1027 @retval QCBOR_ERR_HIT_END
1028
1029 @retval QCBOR_ERR_INT_OVERFLOW
1030
1031 @retval QCBOR_ERR_STRING_ALLOCATE
1032
1033 @retval QCBOR_ERR_STRING_TOO_LONG
1034
1035 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1036
1037 @retval QCBOR_ERR_BAD_TYPE_7
1038
1039 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1040
1041 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001043static inline QCBORError
1044GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001046 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001047
1048 // Get pointer to string allocator. First use is to pass it to
1049 // GetNext_Item() when option is set to allocate for *every* string.
1050 // Second use here is to allocate space to coallese indefinite
1051 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001052 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1053 &(me->StringAllocator) :
1054 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001056 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001057 nReturn = GetNext_Item(&(me->InBuf),
1058 pDecodedItem,
1059 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 if(nReturn) {
1061 goto Done;
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301065 // code in this function from here down can be eliminated. Run tests, except
1066 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001068 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001069 const uint8_t uStringType = pDecodedItem->uDataType;
1070 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 goto Done; // no need to do any work here on non-string types
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001074 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301075 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001076 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301079 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001080 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1082 goto Done;
1083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundblade4b270642020-08-14 12:53:07 -07001085 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001086 UsefulBufC FullString = NULLUsefulBufC;
1087
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001088 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001089 // Get item for next chunk
1090 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001091 // NULL string allocator passed here. Do not need to allocate
1092 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001093 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001094 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001095 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301098 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001099 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001100 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301102 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103 break;
1104 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001106 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301107 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001108 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001109 if(StringChunkItem.uDataType != uStringType ||
1110 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001111 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 break;
1113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301115 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001116 // The first time throurgh FullString.ptr is NULL and this is
1117 // equivalent to StringAllocator_Allocate()
1118 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1119 UNCONST_POINTER(FullString.ptr),
1120 FullString.len + StringChunkItem.val.string.len);
1121
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001122 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301123 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001124 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 break;
1126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001128 // Copy new string chunk at the end of string so far.
1129 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001131
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001132 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1133 // Getting the item failed, clean up the allocated memory
1134 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001136
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001137Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 return nReturn;
1139}
1140
Laurence Lundblade9b334962020-08-27 10:55:53 -07001141static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001142 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001143 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001144 } else if(uTagVal == CBOR_TAG_INVALID16) {
1145 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001146 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001147 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148 return me->auMappedTags[x];
1149 }
1150}
1151
Laurence Lundblade9b334962020-08-27 10:55:53 -07001152
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001153/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001154 Gets all optional tag data items preceding a data item that is not an
1155 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001156
1157 @retval QCBOR_ERR_UNSUPPORTED
1158
1159 @retval QCBOR_ERR_HIT_END
1160
1161 @retval QCBOR_ERR_INT_OVERFLOW
1162
1163 @retval QCBOR_ERR_STRING_ALLOCATE
1164
1165 @retval QCBOR_ERR_STRING_TOO_LONG
1166
1167 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1168
1169 @retval QCBOR_ERR_BAD_TYPE_7
1170
1171 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1172
1173 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1174
1175 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001177static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001178GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001180 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1181 CBOR_TAG_INVALID16,
1182 CBOR_TAG_INVALID16,
1183 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001184
Laurence Lundblade9b334962020-08-27 10:55:53 -07001185 QCBORError uReturn = QCBOR_SUCCESS;
1186
Laurence Lundblade59289e52019-12-30 13:44:37 -08001187 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001188 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001189 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1190 if(uErr != QCBOR_SUCCESS) {
1191 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001192 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001194
Laurence Lundblade9b334962020-08-27 10:55:53 -07001195 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001196 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001197 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001198 break;
1199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundblade9b334962020-08-27 10:55:53 -07001201 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1202 // No room in the tag list
1203 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1204 // Continue on to get all tags on this item even though
1205 // it is erroring out in the end. This is a resource limit
1206 // error, not an problem with being well-formed CBOR.
1207 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209 // Slide tags over one in the array to make room at index 0
1210 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1211 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001212 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001213
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001215 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001216 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001217 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001218 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001219 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001220 break;
1221 }
1222 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1223 break;
1224 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001225 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001226 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1227 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001228 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1229 // Continue on to get all tags on this item even though
1230 // it is erroring out in the end. This is a resource limit
1231 // error, not an problem with being well-formed CBOR.
1232 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001233 }
1234
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001235 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001236 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001237 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238
1239 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001241 }
1242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001245 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246}
1247
1248
1249/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001250 This layer takes care of map entries. It combines the label and data
1251 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001252
1253 @retval QCBOR_ERR_UNSUPPORTED
1254
1255 @retval QCBOR_ERR_HIT_END
1256
1257 @retval QCBOR_ERR_INT_OVERFLOW
1258
1259 @retval QCBOR_ERR_STRING_ALLOCATE
1260
1261 @retval QCBOR_ERR_STRING_TOO_LONG
1262
1263 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1264
1265 @retval QCBOR_ERR_BAD_TYPE_7
1266
1267 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1268
1269 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1270
1271 @retval QCBOR_ERR_TOO_MANY_TAGS
1272
1273 @retval QCBOR_ERR_MAP_LABEL_TYPE
1274
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001275 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001276 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001277static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001279{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001280 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282 if(nReturn)
1283 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001284
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001285 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001286 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001287 goto Done;
1288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001289
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001290 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1291 // In a map and caller wants maps decoded, not treated as arrays
1292
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001293 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001294 // If in a map and the right decoding mode, get the label
1295
Laurence Lundbladeee851742020-01-08 08:37:05 -08001296 // Save label in pDecodedItem and get the next which will
1297 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001298 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001299 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001300 if(nReturn)
1301 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001302
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301303 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001304
1305 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1306 // strings are always good labels
1307 pDecodedItem->label.string = LabelItem.val.string;
1308 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1309 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001310 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001311 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1312 goto Done;
1313 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1314 pDecodedItem->label.int64 = LabelItem.val.int64;
1315 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1316 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1317 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1318 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1319 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1320 pDecodedItem->label.string = LabelItem.val.string;
1321 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1322 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1323 } else {
1324 // label is not an int or a string. It is an arrray
1325 // or a float or such and this implementation doesn't handle that.
1326 // Also, tags on labels are ignored.
1327 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1328 goto Done;
1329 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001330 }
1331 } else {
1332 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001333 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001334 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001335 goto Done;
1336 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001337 // Decoding a map as an array
1338 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001339 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1340 // Cast is needed because of integer promotion
1341 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001342 }
1343 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001344
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001345Done:
1346 return nReturn;
1347}
1348
1349
Laurence Lundblade02625d42020-06-25 14:41:41 -07001350/*
1351 See if next item is a CBOR break. If it is, it is consumed,
1352 if not it is not consumed.
1353*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001354static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001355NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1356{
1357 *pbNextIsBreak = false;
1358 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001359 QCBORItem Peek;
1360 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1361 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1362 if(uReturn != QCBOR_SUCCESS) {
1363 return uReturn;
1364 }
1365 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001366 // It is not a break, rewind so it can be processed normally.
1367 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001368 } else {
1369 *pbNextIsBreak = true;
1370 }
1371 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001372
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001373 return QCBOR_SUCCESS;
1374}
1375
1376
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001377/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001378 An item was just consumed, now figure out if it was the
1379 end of an array or map that can be closed out. That
1380 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001381*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001382static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001383{
1384 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001385
Laurence Lundblade642282a2020-06-23 12:00:33 -07001386 /* This loops ascending nesting levels as long as there is ascending to do */
1387 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1388
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001389 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001390 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001391 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1392 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001393 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001394 break;
1395 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001396 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001397
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001398 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001399 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001400 bool bIsBreak = false;
1401 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1402 if(uReturn != QCBOR_SUCCESS) {
1403 goto Done;
1404 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001405
1406 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001407 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001408 break;
1409 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001410
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001411 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001412 /*
1413 Break occurred inside a bstr-wrapped CBOR or
1414 in the top level sequence. This is always an
1415 error because neither are an indefinte length
1416 map/array.
1417 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001418 uReturn = QCBOR_ERR_BAD_BREAK;
1419 goto Done;
1420 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001421
Laurence Lundblade02625d42020-06-25 14:41:41 -07001422 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001423 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001424
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001427 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001428 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001429 /* 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 -07001430 if(bMarkEnd) {
1431 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001432 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001433
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001434 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001435 break;
1436 }
1437
1438 /* Finally, actually ascend one level. */
1439 DecodeNesting_Ascend(&(pMe->nesting));
1440 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001441
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001442 uReturn = QCBOR_SUCCESS;
1443
1444Done:
1445 return uReturn;
1446}
1447
1448
1449/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001450 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001451 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1452 indefinte length maps and arrays by looking at the item count or
1453 finding CBOR breaks. It detects the ends of the top-level sequence
1454 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001455
1456 @retval QCBOR_ERR_UNSUPPORTED X
1457
1458 @retval QCBOR_ERR_HIT_END
1459
1460 @retval QCBOR_ERR_INT_OVERFLOW X
1461
1462 @retval QCBOR_ERR_STRING_ALLOCATE
1463
1464 @retval QCBOR_ERR_STRING_TOO_LONG
1465
1466 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1467
1468 @retval QCBOR_ERR_BAD_TYPE_7 X
1469
1470 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1471
1472 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1473
1474 @retval QCBOR_ERR_TOO_MANY_TAGS
1475
1476 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1477
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001478 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001479
1480 @retval QCBOR_ERR_NO_MORE_ITEMS
1481
1482 @retval QCBOR_ERR_BAD_BREAK
1483
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001484 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001485static QCBORError
1486QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001487{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001488 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001489 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001490
Laurence Lundblade642282a2020-06-23 12:00:33 -07001491 /*
1492 If out of bytes to consume, it is either the end of the top-level
1493 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001494
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1496 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1497 CBOR is exited, the length is set back to the top-level's length
1498 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001499 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001500 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001501 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001502 goto Done;
1503 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001504
Laurence Lundblade642282a2020-06-23 12:00:33 -07001505 /*
1506 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001507 array. The check for the end of an indefinite length array is
1508 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001509 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001510 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001511 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001512 goto Done;
1513 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001514
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001515 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001516 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001517 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1518 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001519 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001520 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301521
Laurence Lundblade642282a2020-06-23 12:00:33 -07001522 /*
1523 Breaks ending arrays/maps are always processed at the end of this
1524 function. They should never show up here.
1525 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301526 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001527 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301528 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301529 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001530
Laurence Lundblade642282a2020-06-23 12:00:33 -07001531 /*
1532 Record the nesting level for this data item before processing any
1533 of decrementing and descending.
1534 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001535 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001536
Laurence Lundblade642282a2020-06-23 12:00:33 -07001537
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001538 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001539 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001540 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001541 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001542
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001543 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001544 of in the next chunk of code.
1545
1546 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001547 encloses them so a decrement needs to be done for them too, but
1548 that is done only when all the items in them have been
1549 processed, not when they are opened with the exception of an
1550 empty map or array.
1551 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001552 QCBORError uDescendErr;
1553 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001554 pDecodedItem->uDataType,
1555 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001556 if(uDescendErr != QCBOR_SUCCESS) {
1557 /* This error is probably a traversal error and it
1558 overrides the non-traversal error. */
1559 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001560 goto Done;
1561 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001562 }
1563
Laurence Lundblade02625d42020-06-25 14:41:41 -07001564 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1565 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1566 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001567 /*
1568 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001569 - A non-aggregate like an integer or string
1570 - An empty definite length map or array
1571 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001572
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001573 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001574 definite length map/array and break detection for an indefinite
1575 length map/array. If the end of the map/array was reached, then
1576 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001577 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001578 QCBORError uAscendErr;
1579 uAscendErr = NestLevelAscender(me, true);
1580 if(uAscendErr != QCBOR_SUCCESS) {
1581 /* This error is probably a traversal error and it
1582 overrides the non-traversal error. */
1583 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001584 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001585 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301586 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001587
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001588 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001589 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001590 Tell the caller what level is next. This tells them what
1591 maps/arrays were closed out and makes it possible for them to
1592 reconstruct the tree with just the information returned in
1593 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001594 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001595 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001596 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001597 pDecodedItem->uNextNestLevel = 0;
1598 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001599 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001600 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001601
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001602Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001603 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001604 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001605 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1606 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1607 // memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001608 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001609 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001610}
1611
Laurence Lundblade9b334962020-08-27 10:55:53 -07001612static void ShiftTags(QCBORItem *pDecodedItem)
1613{
1614 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1615 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1616 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1617 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1618}
1619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001620
Laurence Lundblade59289e52019-12-30 13:44:37 -08001621/*
1622 Mostly just assign the right data type for the date string.
1623 */
1624inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1625{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001626 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1627 return QCBOR_ERR_BAD_OPT_TAG;
1628 }
1629
1630 const UsefulBufC Temp = pDecodedItem->val.string;
1631 pDecodedItem->val.dateString = Temp;
1632 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001633 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001634 return QCBOR_SUCCESS;
1635}
1636
1637
Laurence Lundblade9b334962020-08-27 10:55:53 -07001638
Laurence Lundblade59289e52019-12-30 13:44:37 -08001639/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001640 The epoch formatted date. Turns lots of different forms of encoding
1641 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001642 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001643static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001644{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001645 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001646
1647 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1648
1649 switch (pDecodedItem->uDataType) {
1650
1651 case QCBOR_TYPE_INT64:
1652 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1653 break;
1654
1655 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001656 // This only happens for CBOR type 0 > INT64_MAX so it is
1657 // always an overflow.
1658 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1659 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001660 break;
1661
1662 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001663 case QCBOR_TYPE_FLOAT:
1664#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001665 {
1666 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001667 // conversion to an int64_t to be able to detect doubles that
1668 // are too large to fit into an int64_t. A double has 52
1669 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1670 // to a double actually causes a round up which is bad and
1671 // wrong for the comparison because it will allow conversion
1672 // of doubles that can't fit into a uint64_t. To remedy this
1673 // INT64_MAX - 0x7ff is used as the cutoff point because if
1674 // that value rounds up in conversion to double it will still
1675 // be less than INT64_MAX. 0x7ff is picked because it has 11
1676 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001677 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001678 // INT64_MAX seconds is on the order of 10 billion years, and
1679 // the earth is less than 5 billion years old, so for most
1680 // uses this conversion error won't occur even though doubles
1681 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001682 //
1683 // Without the 0x7ff there is a ~30 minute range of time
1684 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001685 // where this code would go wrong. Some compilers
1686 // will generate warnings or errors without the 0x7ff
1687 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001688 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1689 pDecodedItem->val.dfnum :
1690 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001691 if(isnan(d) ||
1692 d > (double)(INT64_MAX - 0x7ff) ||
1693 d < (double)(INT64_MIN + 0x7ff)) {
1694 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001695 goto Done;
1696 }
1697 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001698 pDecodedItem->val.epochDate.fSecondsFraction =
1699 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001700 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001701#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001702
Laurence Lundbladec7114722020-08-13 05:11:40 -07001703 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001704 goto Done;
1705
Laurence Lundblade9682a532020-06-06 18:33:04 -07001706#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001707 break;
1708
1709 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001710 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001711 goto Done;
1712 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001713
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1715
1716Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001717 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001718}
1719
1720
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001721/*
1722 Mostly just assign the right data type for the bignum.
1723 */
1724inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1725{
1726 // Stack Use: UsefulBuf 1 -- 16
1727 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1728 return QCBOR_ERR_BAD_OPT_TAG;
1729 }
1730 const UsefulBufC Temp = pDecodedItem->val.string;
1731 pDecodedItem->val.bigNum = Temp;
1732 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1733 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1734 : QCBOR_TYPE_NEGBIGNUM);
1735 return QCBOR_SUCCESS;
1736}
1737
1738
Laurence Lundblade59289e52019-12-30 13:44:37 -08001739#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1740/*
1741 Decode decimal fractions and big floats.
1742
1743 When called pDecodedItem must be the array that is tagged as a big
1744 float or decimal fraction, the array that has the two members, the
1745 exponent and mantissa.
1746
1747 This will fetch and decode the exponent and mantissa and put the
1748 result back into pDecodedItem.
1749 */
1750inline static QCBORError
1751QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1752{
1753 QCBORError nReturn;
1754
1755 // --- Make sure it is an array; track nesting level of members ---
1756 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1757 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1758 goto Done;
1759 }
1760
1761 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001762 // definite length arrays, but not for indefnite. Instead remember
1763 // the nesting level the two integers must be at, which is one
1764 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001765 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1766
1767 // --- Is it a decimal fraction or a bigfloat? ---
1768 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1769 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1770
1771 // --- Get the exponent ---
1772 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001773 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001774 if(nReturn != QCBOR_SUCCESS) {
1775 goto Done;
1776 }
1777 if(exponentItem.uNestingLevel != nNestLevel) {
1778 // Array is empty or a map/array encountered when expecting an int
1779 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1780 goto Done;
1781 }
1782 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1783 // Data arriving as an unsigned int < INT64_MAX has been converted
1784 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1785 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1786 // will be too large for this to handle and thus an error that will
1787 // get handled in the next else.
1788 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1789 } else {
1790 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1791 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1792 goto Done;
1793 }
1794
1795 // --- Get the mantissa ---
1796 QCBORItem mantissaItem;
1797 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1798 if(nReturn != QCBOR_SUCCESS) {
1799 goto Done;
1800 }
1801 if(mantissaItem.uNestingLevel != nNestLevel) {
1802 // Mantissa missing or map/array encountered when expecting number
1803 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1804 goto Done;
1805 }
1806 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1807 // Data arriving as an unsigned int < INT64_MAX has been converted
1808 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1809 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1810 // will be too large for this to handle and thus an error that
1811 // will get handled in an else below.
1812 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1813 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1814 // Got a good big num mantissa
1815 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1816 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001817 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1818 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1819 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001820 } else {
1821 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1822 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1823 goto Done;
1824 }
1825
1826 // --- Check that array only has the two numbers ---
1827 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001828 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001832 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833
1834Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 return nReturn;
1836}
1837#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1838
1839
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001840inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1841{
1842 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1843 return QCBOR_ERR_BAD_OPT_TAG;
1844 }
1845 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1846 return QCBOR_SUCCESS;
1847}
1848
1849
1850inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1851{
1852 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1853 return QCBOR_ERR_BAD_OPT_TAG;
1854 }
1855 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001856
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001857 return QCBOR_SUCCESS;
1858}
1859
1860
1861inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1862{
1863 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1864 return QCBOR_ERR_BAD_OPT_TAG;
1865 }
1866 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001867
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001868 return QCBOR_SUCCESS;
1869}
1870
1871
1872inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1873{
1874 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1875 return QCBOR_ERR_BAD_OPT_TAG;
1876 }
1877 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001878
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001879 return QCBOR_SUCCESS;
1880}
1881
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001882
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001883inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1884{
1885 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1886 return QCBOR_ERR_BAD_OPT_TAG;
1887 }
1888 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001889
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001890 return QCBOR_SUCCESS;
1891}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001892
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001893
1894inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1895{
1896 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1897 return QCBOR_ERR_BAD_OPT_TAG;
1898 }
1899 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001900
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001901 return QCBOR_SUCCESS;
1902}
1903
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001904
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001905inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1906{
1907 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1908 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001909 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001910 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1911 } else {
1912 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001913
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001915
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001916 return QCBOR_SUCCESS;
1917}
1918
1919
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001920inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1921{
1922 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1923 return QCBOR_ERR_BAD_OPT_TAG;
1924 }
1925 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001926
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001927 return QCBOR_SUCCESS;
1928}
1929
1930
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001932 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001933 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001934QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001935QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001936{
1937 QCBORError nReturn;
1938
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001939 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001940 if(nReturn != QCBOR_SUCCESS) {
1941 goto Done;
1942 }
1943
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001944 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001945 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001947 // Many of the functions here only just map a CBOR tag to
1948 // a QCBOR_TYPE for a string and could probably be
1949 // implemented with less object code. This implementation
1950 // of string types takes about 120 bytes of object code
1951 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001952 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001953 nReturn = DecodeDateString(pDecodedItem);
1954 break;
1955
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001956 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957 nReturn = DecodeDateEpoch(pDecodedItem);
1958 break;
1959
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001960 case CBOR_TAG_POS_BIGNUM:
1961 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 nReturn = DecodeBigNum(pDecodedItem);
1963 break;
1964
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001965 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1966 case CBOR_TAG_DECIMAL_FRACTION:
1967 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 // For aggregate tagged types, what goes into pTags is only collected
1969 // from the surrounding data item, not the contents, so pTags is not
1970 // passed on here.
1971
1972 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1973 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001974 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001975
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001976 case CBOR_TAG_CBOR:
1977 nReturn = DecodeWrappedCBOR(pDecodedItem);
1978 break;
1979
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001980 case CBOR_TAG_CBOR_SEQUENCE:
1981 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1982 break;
1983
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001984 case CBOR_TAG_URI:
1985 nReturn = DecodeURI(pDecodedItem);
1986 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001987
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001988 case CBOR_TAG_B64URL:
1989 nReturn = DecodeB64URL(pDecodedItem);
1990 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001991
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001992 case CBOR_TAG_B64:
1993 nReturn = DecodeB64(pDecodedItem);
1994 break;
1995
1996 case CBOR_TAG_MIME:
1997 case CBOR_TAG_BINARY_MIME:
1998 nReturn = DecodeMIME(pDecodedItem);
1999 break;
2000
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002001 case CBOR_TAG_REGEX:
2002 nReturn = DecodeRegex(pDecodedItem);
2003 break;
2004
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002005 case CBOR_TAG_BIN_UUID:
2006 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002007 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002008
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002009 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002010 // The end of the tag list or no tags
2011 // Successful exit from the loop.
2012 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002013
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002014 default:
2015 // A tag that is not understood
2016 // A successful exit from the loop
2017 goto Done;
2018
2019 }
2020 if(nReturn != QCBOR_SUCCESS) {
2021 goto Done;
2022 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002023 // A tag was successfully processed, shift it
2024 // out of the list of tags returned.
2025 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 }
2027
2028Done:
2029 if(nReturn != QCBOR_SUCCESS) {
2030 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2031 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2032 }
2033 return nReturn;
2034}
2035
2036
2037/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002038 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002040void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2041{
2042 if(pMe->uLastError != QCBOR_SUCCESS) {
2043 return;
2044 }
2045
2046 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2047}
2048
2049
2050/*
2051 Public function, see header qcbor/qcbor_decode.h file
2052 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002053QCBORError
2054QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2055 QCBORItem *pDecodedItem,
2056 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002057{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002058 QCBORError nReturn;
2059
2060 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2061 if(nReturn != QCBOR_SUCCESS) {
2062 return nReturn;
2063 }
2064
2065 if(pTags != NULL) {
2066 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002067 // Reverse the order because pTags is reverse of
2068 // QCBORItem.uTags.
2069 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002070 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002071 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002072 }
2073 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2074 return QCBOR_ERR_TOO_MANY_TAGS;
2075 }
2076 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2077 pTags->uNumUsed++;
2078 }
2079 }
2080
2081 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002082}
2083
2084
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002085/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302086 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302087 next one down. If a layer has no work to do for a particular item
2088 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002089
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2091 tagged data items, turning them into the local C representation.
2092 For the most simple it is just associating a QCBOR_TYPE with the data. For
2093 the complex ones that an aggregate of data items, there is some further
2094 decoding and a little bit of recursion.
2095
2096 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302097 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302098 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002099 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002100
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302101 - GetNext_MapEntry -- This handles the combining of two
2102 items, the label and the data, that make up a map entry.
2103 It only does work on maps. It combines the label and data
2104 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002105
Laurence Lundblade59289e52019-12-30 13:44:37 -08002106 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2107 tags into bit flags associated with the data item. No actual decoding
2108 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002109
Laurence Lundblade59289e52019-12-30 13:44:37 -08002110 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302111 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302112 string allocater to create contiguous space for the item. It
2113 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundblade59289e52019-12-30 13:44:37 -08002115 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2116 atomic data item has a "major type", an integer "argument" and optionally
2117 some content. For text and byte strings, the content is the bytes
2118 that make up the string. These are the smallest data items that are
2119 considered to be well-formed. The content may also be other data items in
2120 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002121
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002122 Roughly this takes 300 bytes of stack for vars. Need to
2123 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002124
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302125 */
2126
2127
2128/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002129 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002130 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002131bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002132 const QCBORItem *pItem,
2133 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002134{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002135 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002136 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002137 break;
2138 }
2139 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002140 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002141 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002142 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002143
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002144 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002145}
2146
2147
2148/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002149 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002150 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002151QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002152{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002153 QCBORError uReturn = me->uLastError;
2154
2155 if(uReturn != QCBOR_SUCCESS) {
2156 goto Done;
2157 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002158
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002159 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002160 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002161 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002162 goto Done;
2163 }
2164
2165 // Error out if not all the bytes are consumed
2166 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002167 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002168 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002169
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002170Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302171 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002172 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002173 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002174
Laurence Lundblade085d7952020-07-24 10:26:30 -07002175 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002176}
2177
2178
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002179/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002180 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002181*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002182// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002183uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2184 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002185 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002186{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002187 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2188 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002189 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002190 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002191 }
2192}
2193
Laurence Lundblade9b334962020-08-27 10:55:53 -07002194/*
2195 Public function, see header qcbor/qcbor_decode.h file
2196*/
2197uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2198 uint32_t uIndex)
2199{
2200 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2201 return CBOR_TAG_INVALID64;
2202 } else {
2203 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2204 }
2205}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002206
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002207/*
2208
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002209Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210
Laurence Lundbladeee851742020-01-08 08:37:05 -08002211 - Hit end of input before it was expected while decoding type and
2212 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002213
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002214 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002215
Laurence Lundbladeee851742020-01-08 08:37:05 -08002216 - Hit end of input while decoding a text or byte string
2217 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002218
Laurence Lundbladeee851742020-01-08 08:37:05 -08002219 - Encountered conflicting tags -- e.g., an item is tagged both a date
2220 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002221
Laurence Lundbladeee851742020-01-08 08:37:05 -08002222 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002223 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundbladeee851742020-01-08 08:37:05 -08002225 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002226 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundbladeee851742020-01-08 08:37:05 -08002228 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2229 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002230
Laurence Lundbladeee851742020-01-08 08:37:05 -08002231 - The type of a map label is not a string or int
2232 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002234 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002235
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002236 */
2237
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002238
2239
Laurence Lundbladef6531662018-12-04 10:42:22 +09002240
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002241/* ===========================================================================
2242 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002243
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002244 This implements a simple sting allocator for indefinite length
2245 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2246 implements the function type QCBORStringAllocate and allows easy
2247 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002248
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002249 This particular allocator is built-in for convenience. The caller
2250 can implement their own. All of this following code will get
2251 dead-stripped if QCBORDecode_SetMemPool() is not called.
2252
2253 This is a very primitive memory allocator. It does not track
2254 individual allocations, only a high-water mark. A free or
2255 reallocation must be of the last chunk allocated.
2256
2257 The size of the pool and offset to free memory are packed into the
2258 first 8 bytes of the memory pool so we don't have to keep them in
2259 the decode context. Since the address of the pool may not be
2260 aligned, they have to be packed and unpacked as if they were
2261 serialized data of the wire or such.
2262
2263 The sizes packed in are uint32_t to be the same on all CPU types
2264 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002265 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002266
2267
Laurence Lundbladeee851742020-01-08 08:37:05 -08002268static inline int
2269MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002270{
2271 // Use of UsefulInputBuf is overkill, but it is convenient.
2272 UsefulInputBuf UIB;
2273
Laurence Lundbladeee851742020-01-08 08:37:05 -08002274 // Just assume the size here. It was checked during SetUp so
2275 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002276 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2277 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2278 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2279 return UsefulInputBuf_GetError(&UIB);
2280}
2281
2282
Laurence Lundbladeee851742020-01-08 08:37:05 -08002283static inline int
2284MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002285{
2286 // Use of UsefulOutBuf is overkill, but convenient. The
2287 // length check performed here is useful.
2288 UsefulOutBuf UOB;
2289
2290 UsefulOutBuf_Init(&UOB, Pool);
2291 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2292 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2293 return UsefulOutBuf_GetError(&UOB);
2294}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002295
2296
2297/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002298 Internal function for an allocation, reallocation free and destuct.
2299
2300 Having only one function rather than one each per mode saves space in
2301 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002302
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002303 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2304 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002305static UsefulBuf
2306MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002307{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002308 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002309
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002310 uint32_t uPoolSize;
2311 uint32_t uFreeOffset;
2312
2313 if(uNewSize > UINT32_MAX) {
2314 // This allocator is only good up to 4GB. This check should
2315 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2316 goto Done;
2317 }
2318 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2319
2320 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2321 goto Done;
2322 }
2323
2324 if(uNewSize) {
2325 if(pMem) {
2326 // REALLOCATION MODE
2327 // Calculate pointer to the end of the memory pool. It is
2328 // assumed that pPool + uPoolSize won't wrap around by
2329 // assuming the caller won't pass a pool buffer in that is
2330 // not in legitimate memory space.
2331 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2332
2333 // Check that the pointer for reallocation is in the range of the
2334 // pool. This also makes sure that pointer math further down
2335 // doesn't wrap under or over.
2336 if(pMem >= pPool && pMem < pPoolEnd) {
2337 // Offset to start of chunk for reallocation. This won't
2338 // wrap under because of check that pMem >= pPool. Cast
2339 // is safe because the pool is always less than UINT32_MAX
2340 // because of check in QCBORDecode_SetMemPool().
2341 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2342
2343 // Check to see if the allocation will fit. uPoolSize -
2344 // uMemOffset will not wrap under because of check that
2345 // pMem is in the range of the uPoolSize by check above.
2346 if(uNewSize <= uPoolSize - uMemOffset) {
2347 ReturnValue.ptr = pMem;
2348 ReturnValue.len = uNewSize;
2349
2350 // Addition won't wrap around over because uNewSize was
2351 // checked to be sure it is less than the pool size.
2352 uFreeOffset = uMemOffset + uNewSize32;
2353 }
2354 }
2355 } else {
2356 // ALLOCATION MODE
2357 // uPoolSize - uFreeOffset will not underflow because this
2358 // pool implementation makes sure uFreeOffset is always
2359 // smaller than uPoolSize through this check here and
2360 // reallocation case.
2361 if(uNewSize <= uPoolSize - uFreeOffset) {
2362 ReturnValue.len = uNewSize;
2363 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002364 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002365 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002366 }
2367 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002368 if(pMem) {
2369 // FREE MODE
2370 // Cast is safe because of limit on pool size in
2371 // QCBORDecode_SetMemPool()
2372 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2373 } else {
2374 // DESTRUCT MODE
2375 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002376 }
2377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002378
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002379 UsefulBuf Pool = {pPool, uPoolSize};
2380 MemPool_Pack(Pool, uFreeOffset);
2381
2382Done:
2383 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002384}
2385
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002386
Laurence Lundbladef6531662018-12-04 10:42:22 +09002387/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002388 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002389 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002390QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2391 UsefulBuf Pool,
2392 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002393{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002394 // The pool size and free mem offset are packed into the beginning
2395 // of the pool memory. This compile time check make sure the
2396 // constant in the header is correct. This check should optimize
2397 // down to nothing.
2398 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002399 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002400 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002401
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002402 // The pool size and free offset packed in to the beginning of pool
2403 // memory are only 32-bits. This check will optimize out on 32-bit
2404 // machines.
2405 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002406 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002407 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002408
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002409 // This checks that the pool buffer given is big enough.
2410 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002411 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002412 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002413
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002414 pMe->StringAllocator.pfAllocator = MemPool_Function;
2415 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2416 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002417
Laurence Lundblade30816f22018-11-10 13:40:22 +07002418 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002419}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002420
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002421
2422
Laurence Lundblade9b334962020-08-27 10:55:53 -07002423static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2424{
2425 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2426}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002427
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002428
2429/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002430 Consume an entire map or array (and do next to
2431 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002432 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002433static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002434ConsumeItem(QCBORDecodeContext *pMe,
2435 const QCBORItem *pItemToConsume,
2436 uint_fast8_t *puNextNestLevel)
2437{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002438 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002439 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002440
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002441 // If it is a map or array, this will tell if it is empty.
2442 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2443
2444 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2445 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002446
Laurence Lundblade1341c592020-04-11 14:19:05 -07002447 /* This works for definite and indefinite length
2448 * maps and arrays by using the nesting level
2449 */
2450 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002451 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002452 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002453 goto Done;
2454 }
2455 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002456
Laurence Lundblade1341c592020-04-11 14:19:05 -07002457 if(puNextNestLevel != NULL) {
2458 *puNextNestLevel = Item.uNextNestLevel;
2459 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002460 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002461
Laurence Lundblade1341c592020-04-11 14:19:05 -07002462 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002463 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002464 if(puNextNestLevel != NULL) {
2465 /* Just pass the nesting level through */
2466 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2467 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002468 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002469 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002470
2471Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002472 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002473}
2474
2475
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476/* Return true if the labels in Item1 and Item2 are the same.
2477 Works only for integer and string labels. Returns false
2478 for any other type. */
2479static inline bool
2480MatchLabel(QCBORItem Item1, QCBORItem Item2)
2481{
2482 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2483 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2484 return true;
2485 }
2486 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002487 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002488 return true;
2489 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002490 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002491 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2492 return true;
2493 }
2494 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2495 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2496 return true;
2497 }
2498 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002499
Laurence Lundblade1341c592020-04-11 14:19:05 -07002500 /* Other label types are never matched */
2501 return false;
2502}
2503
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002504
2505/*
2506 Returns true if Item1 and Item2 are the same type
2507 or if either are of QCBOR_TYPE_ANY.
2508 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002509static inline bool
2510MatchType(QCBORItem Item1, QCBORItem Item2)
2511{
2512 if(Item1.uDataType == Item2.uDataType) {
2513 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002514 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002515 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002516 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002517 return true;
2518 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002519 return false;
2520}
2521
2522
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002523/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002524 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002525
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002526 @param[in] pMe The decode context to search.
2527 @param[in,out] pItemArray The items to search for and the items found.
2528 @param[out] puOffset Byte offset of last item matched.
2529 @param[in] pCBContext Context for the not-found item call back.
2530 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002531
2532 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2533
Laurence Lundblade9b334962020-08-27 10:55:53 -07002534 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2535 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2536 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002537
2538 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2539
2540 @retval Also errors returned by QCBORDecode_GetNext().
2541
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002542 On input pItemArray contains a list of labels and data types
2543 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002544
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002545 On output the fully retrieved items are filled in with
2546 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002547
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002548 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002549 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002550// TODO: make this handle indefinite length strings, possibly with
2551// allocation only when returning the string.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002552static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002553MapSearch(QCBORDecodeContext *pMe,
2554 QCBORItem *pItemArray,
2555 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002556 void *pCBContext,
2557 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002558{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002559 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002560 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002561
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002562 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002563 uReturn = pMe->uLastError;
2564 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002565 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002566
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002567 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002568 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2569 /* QCBOR_TYPE_NONE as first item indicates just looking
2570 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002571 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2572 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002573 }
2574
Laurence Lundblade085d7952020-07-24 10:26:30 -07002575 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2576 // It is an empty bounded array or map
2577 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2578 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002579 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002580 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002581 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002582 // Nothing is ever found in an empty array or map. All items
2583 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002584 uReturn = QCBOR_SUCCESS;
2585 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002586 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002587 }
2588
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002589 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002590 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2591
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002592 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002593 UsefulInputBuf_Seek(&(pMe->InBuf),
2594 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002595
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002596 /*
2597 Loop over all the items in the map. They could be
2598 deeply nested and this should handle both definite
2599 and indefinite length maps and arrays, so this
2600 adds some complexity.
2601 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002602 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002603 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002604 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002605 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002606 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002607
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002608 /* Get the item */
2609 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002610 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002611 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002612 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002613 goto Done;
2614 }
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002615 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2616 // Unexpected end of map or array.
2617 goto Done;
2618 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002619
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002620 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002621 bool bMatched = false;
2622 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002623 // TODO: have label filled in on invalid CBOR so error reporting
Laurence Lundblade9b334962020-08-27 10:55:53 -07002624 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002625 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002626 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002627 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2628 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002629 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002630 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002631 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002632 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002633 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002634 goto Done;
2635 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002636
Laurence Lundblade1341c592020-04-11 14:19:05 -07002637 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002638 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002639 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002640 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002641 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002642 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002643 bMatched = true;
2644 }
2645 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002646
2647
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002648 if(!bMatched && pfCallback != NULL) {
2649 /*
2650 Call the callback on unmatched labels.
2651 (It is tempting to do duplicate detection here, but that would
2652 require dynamic memory allocation because the number of labels
2653 that might be encountered is unbounded.)
2654 */
2655 uReturn = (*pfCallback)(pCBContext, &Item);
2656 if(uReturn != QCBOR_SUCCESS) {
2657 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002658 }
2659 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002660
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002661 /*
2662 Consume the item whether matched or not. This
2663 does the work of traversing maps and array and
2664 everything in them. In this loop only the
2665 items at the current nesting level are examined
2666 to match the labels.
2667 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002668 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002669 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002670 goto Done;
2671 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002672
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002673 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002674
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002675 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002676
2677 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002678 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2679 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002680
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002681 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002682 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2683
2684 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002685 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2686 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002687 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002688 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002689 }
2690 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002691
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002692 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002693}
2694
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002695
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002696/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002697 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002698*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002699void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2700 int64_t nLabel,
2701 uint8_t uQcborType,
2702 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002703{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002704 if(pMe->uLastError != QCBOR_SUCCESS) {
2705 return;
2706 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002707
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002708 QCBORItem OneItemSeach[2];
2709 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2710 OneItemSeach[0].label.int64 = nLabel;
2711 OneItemSeach[0].uDataType = uQcborType;
2712 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002713
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002714 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2715 if(uReturn != QCBOR_SUCCESS) {
2716 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002718 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002719 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002720 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 }
2722
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002723 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002724
2725 Done:
2726 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002727}
2728
2729
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002731 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002732*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002733void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2734 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002735 uint8_t uQcborType,
2736 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002737{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002738 if(pMe->uLastError != QCBOR_SUCCESS) {
2739 return;
2740 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002742 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002743 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2744 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2745 OneItemSeach[0].uDataType = uQcborType;
2746 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002747
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002748 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2749 if(uReturn != QCBOR_SUCCESS) {
2750 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002751 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002752 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002753 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002754 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755 }
2756
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002757 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002758
2759Done:
2760 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002761}
2762
2763
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002764
Laurence Lundblade9b334962020-08-27 10:55:53 -07002765static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002766{
2767 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2768 if(uDataType == puTypeList[i]) {
2769 return QCBOR_SUCCESS;
2770 }
2771 }
2772 return QCBOR_ERR_UNEXPECTED_TYPE;
2773}
2774
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002775
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002776/**
2777 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002778 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002779
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002780 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2781 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002782
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002783 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2784 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002785static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002786{
2787 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2788 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2789 /* There are tags that QCBOR couldn't process on this item and
2790 the caller has told us there should not be. */
2791 return QCBOR_ERR_UNEXPECTED_TYPE;
2792 }
2793
2794 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2795 const int nItemType = pItem->uDataType;
2796
2797 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2798 // Must match the tag and only the tag
2799 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2800 }
2801
2802 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2803 if(uReturn == QCBOR_SUCCESS) {
2804 return QCBOR_SUCCESS;
2805 }
2806
2807 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2808 /* Must match the content type and only the content type.
2809 There was no match just above so it is a fail. */
2810 return QCBOR_ERR_UNEXPECTED_TYPE;
2811 }
2812
2813 /* If here it can match either the tag or the content
2814 and it hasn't matched the content, so the end
2815 result is whether it matches the tag. This is
2816 also the case that the CBOR standard discourages. */
2817
2818 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2819}
2820
Laurence Lundblade9b334962020-08-27 10:55:53 -07002821
Laurence Lundblade9b334962020-08-27 10:55:53 -07002822
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002823// This could be semi-private if need be
2824static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002825void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2826 int64_t nLabel,
2827 TagSpecification TagSpec,
2828 QCBORItem *pItem)
2829{
2830 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2831 if(pMe->uLastError != QCBOR_SUCCESS) {
2832 return;
2833 }
2834
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002835 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002836}
2837
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002838
2839// This could be semi-private if need be
2840static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002841void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2842 const char *szLabel,
2843 TagSpecification TagSpec,
2844 QCBORItem *pItem)
2845{
2846 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2847 if(pMe->uLastError != QCBOR_SUCCESS) {
2848 return;
2849 }
2850
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002851 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002852}
2853
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002854// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002855void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2856 int64_t nLabel,
2857 TagSpecification TagSpec,
2858 UsefulBufC *pString)
2859{
2860 QCBORItem Item;
2861 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2862 if(pMe->uLastError == QCBOR_SUCCESS) {
2863 *pString = Item.val.string;
2864 }
2865}
2866
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002867// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002868void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2869 const char * szLabel,
2870 TagSpecification TagSpec,
2871 UsefulBufC *pString)
2872{
2873 QCBORItem Item;
2874 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2875 if(pMe->uLastError == QCBOR_SUCCESS) {
2876 *pString = Item.val.string;
2877 }
2878}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002879
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002880/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002881 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002882*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002883void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002884{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002885 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2886 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002887}
2888
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002889/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002890 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002891*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002892void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2893 QCBORItem *pItemList,
2894 void *pCallbackCtx,
2895 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002896{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002897 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2898 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002899}
2900
2901
Laurence Lundblade34691b92020-05-18 22:25:25 -07002902static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002903{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002904 // The first item in pSearch is the one that is to be
2905 // entered. It should be the only one filled in. Any other
2906 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002907 if(pMe->uLastError != QCBOR_SUCCESS) {
2908 // Already in error state; do nothing.
2909 return;
2910 }
2911
2912 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002913 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002914 if(pMe->uLastError != QCBOR_SUCCESS) {
2915 return;
2916 }
2917
Laurence Lundblade9b334962020-08-27 10:55:53 -07002918 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002919 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002920 return;
2921 }
2922
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002923 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002924 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002925
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002926 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002927 be at the right place.
2928
2929 The UsefulInBuf offset could be anywhere, so no assumption is
2930 made about it.
2931
2932 No assumption is made about the pre-order nesting level either.
2933
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002934 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002935 the map level that is being entered.
2936 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002937 /* Seek to the data item that is the map or array */
2938 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002939
2940 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002941
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002942 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002943}
2944
2945
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002946/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002947 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002948*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002949void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002950{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002951 QCBORItem OneItemSeach[2];
2952 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2953 OneItemSeach[0].label.int64 = nLabel;
2954 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2955 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002956
Laurence Lundblade9b334962020-08-27 10:55:53 -07002957 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002958 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002959}
2960
2961
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002962/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002963 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002964*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002965void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002966{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002967 QCBORItem OneItemSeach[2];
2968 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2969 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2970 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2971 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002972
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002973 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002974}
2975
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002976/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002978*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002979void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002980{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002981 QCBORItem OneItemSeach[2];
2982 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2983 OneItemSeach[0].label.int64 = nLabel;
2984 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2985 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002986
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002987 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002988}
2989
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002990/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002991 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002992*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002993void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2994{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002995 QCBORItem OneItemSeach[2];
2996 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2997 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2998 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2999 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003000
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003001 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003002}
3003
3004
Laurence Lundblade02625d42020-06-25 14:41:41 -07003005// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003006void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003007{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003008 QCBORError uErr;
3009
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003010 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003011 if(pMe->uLastError != QCBOR_SUCCESS) {
3012 // Already in error state; do nothing.
3013 return;
3014 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003015
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003016 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003017 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003018 uErr = QCBORDecode_GetNext(pMe, &Item);
3019 if(uErr != QCBOR_SUCCESS) {
3020 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003021 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003022 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003023 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3024 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003025 }
3026
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003027 CopyTags(pMe, &Item);
3028
3029
Laurence Lundbladef0499502020-08-01 11:55:57 -07003030 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003031 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003032 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3033 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003034 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003035 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3036 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003037 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3038 DecodeNesting_Descend(&(pMe->nesting), uType);
3039 }
3040
Laurence Lundblade02625d42020-06-25 14:41:41 -07003041 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003042
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003043 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3044 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003045
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003046Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003047 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003048}
3049
Laurence Lundblade02625d42020-06-25 14:41:41 -07003050
3051/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003052 This is the common work for exiting a level that is a bounded map, array or bstr
3053 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003054
3055 One chunk of work is to set up the pre-order traversal so it is at
3056 the item just after the bounded map, array or bstr that is being
3057 exited. This is somewhat complex.
3058
3059 The other work is to level-up the bounded mode to next higest bounded
3060 mode or the top level if there isn't one.
3061 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003062static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003063ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003064{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003065 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003066
Laurence Lundblade02625d42020-06-25 14:41:41 -07003067 /*
3068 First the pre-order-traversal byte offset is positioned to the
3069 item just after the bounded mode item that was just consumed.
3070 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003071 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3072
Laurence Lundblade02625d42020-06-25 14:41:41 -07003073 /*
3074 Next, set the current nesting level to one above the bounded level
3075 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003076
Laurence Lundblade02625d42020-06-25 14:41:41 -07003077 DecodeNesting_CheckBoundedType() is always called before this and
3078 makes sure pCurrentBounded is valid.
3079 */
3080 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3081
3082 /*
3083 This does the complex work of leveling up the pre-order traversal
3084 when the end of a map or array or another bounded level is
3085 reached. It may do nothing, or ascend all the way to the top
3086 level.
3087 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003088 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003089 if(uErr != QCBOR_SUCCESS) {
3090 goto Done;
3091 }
3092
Laurence Lundblade02625d42020-06-25 14:41:41 -07003093 /*
3094 This makes the next highest bounded level the current bounded
3095 level. If there is no next highest level, then no bounded mode is
3096 in effect.
3097 */
3098 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003099
Laurence Lundblade02625d42020-06-25 14:41:41 -07003100 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003101
3102Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003103 return uErr;
3104}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003105
Laurence Lundblade02625d42020-06-25 14:41:41 -07003106
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003107// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003108void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003109{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003110 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003111 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003112 return;
3113 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003114
Laurence Lundblade02625d42020-06-25 14:41:41 -07003115 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003116
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003117 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003118 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003119 goto Done;
3120 }
3121
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 /*
3123 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003124 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003125 from previous map search, then do a dummy search.
3126 */
3127 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003128 QCBORItem Dummy;
3129 Dummy.uLabelType = QCBOR_TYPE_NONE;
3130 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3131 if(uErr != QCBOR_SUCCESS) {
3132 goto Done;
3133 }
3134 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003135
Laurence Lundblade02625d42020-06-25 14:41:41 -07003136 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003137
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003138Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003139 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003140}
3141
3142
Laurence Lundblade1341c592020-04-11 14:19:05 -07003143
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003144static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003145 const QCBORItem *pItem,
3146 uint8_t uTagRequirement,
3147 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003148{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003149 if(pBstr) {
3150 *pBstr = NULLUsefulBufC;
3151 }
3152
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003153 if(pMe->uLastError != QCBOR_SUCCESS) {
3154 // Already in error state; do nothing.
3155 return pMe->uLastError;
3156 }
3157
3158 QCBORError uError = QCBOR_SUCCESS;
3159
3160 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3161 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3162 goto Done;;
3163 }
3164
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003165 const TagSpecification TagSpec =
3166 {
3167 uTagRequirement,
3168 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3169 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3170 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003171
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003172 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003173 if(uError != QCBOR_SUCCESS) {
3174 goto Done;
3175 }
3176
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003177 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003178 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003179 so the increment in NestLevelAscender called by ExitBoundedLevel()
3180 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003181 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003182 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003183
3184 if(pBstr) {
3185 *pBstr = pItem->val.string;
3186 }
3187
3188 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003189
3190 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003191 // Most of these calls are simple inline accessors so this doesn't
3192 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003193 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003194 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3195 // TODO: test this error condition
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003196 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003197 goto Done;
3198 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003199 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003200 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003201
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003202 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003203 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003204 (uint32_t)uPreviousLength,
3205 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003206Done:
3207 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003208}
3209
3210
Laurence Lundblade02625d42020-06-25 14:41:41 -07003211/*
3212 Public function, see header qcbor/qcbor_decode.h file
3213 */
3214void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003215 uint8_t uTagRequirement,
3216 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003217{
3218 if(pMe->uLastError != QCBOR_SUCCESS) {
3219 // Already in error state; do nothing.
3220 return;
3221 }
3222
3223 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003224 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003225 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3226 if(pMe->uLastError != QCBOR_SUCCESS) {
3227 return;
3228 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003229
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003230 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003231 &Item,
3232 uTagRequirement,
3233 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003234}
3235
3236
Laurence Lundblade02625d42020-06-25 14:41:41 -07003237/*
3238 Public function, see header qcbor/qcbor_decode.h file
3239 */
3240void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003241 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003242 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003243 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003244{
3245 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003246 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003247
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003248 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003249}
3250
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003251
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252/*
3253 Public function, see header qcbor/qcbor_decode.h file
3254 */
3255void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003256 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003257 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003258 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003259{
3260 QCBORItem Item;
3261 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3262
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003263 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003264}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003265
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003266
Laurence Lundblade02625d42020-06-25 14:41:41 -07003267/*
3268 Public function, see header qcbor/qcbor_decode.h file
3269 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003270void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003271{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003272 if(pMe->uLastError != QCBOR_SUCCESS) {
3273 // Already in error state; do nothing.
3274 return;
3275 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003276
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003277 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003278 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003279 return;
3280 }
3281
3282 /*
3283 Reset the length of the UsefulInputBuf to what it was before
3284 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003285 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003286 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3287 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003288
3289
Laurence Lundblade02625d42020-06-25 14:41:41 -07003290 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003291 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003292}
3293
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003294
Laurence Lundbladee6430642020-03-14 21:15:44 -07003295
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003296
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003297
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003298
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003299
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003300
Laurence Lundblade9b334962020-08-27 10:55:53 -07003301static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003302{
3303 switch(pItem->uDataType) {
3304 case QCBOR_TYPE_TRUE:
3305 *pBool = true;
3306 return QCBOR_SUCCESS;
3307 break;
3308
3309 case QCBOR_TYPE_FALSE:
3310 *pBool = false;
3311 return QCBOR_SUCCESS;
3312 break;
3313
3314 default:
3315 return QCBOR_ERR_UNEXPECTED_TYPE;
3316 break;
3317 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003318 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003319}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003320
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003321
Laurence Lundblade9b334962020-08-27 10:55:53 -07003322
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003323/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003324 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003325*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003326void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003327{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003328 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003329 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003330 return;
3331 }
3332
Laurence Lundbladec4537442020-04-14 18:53:22 -07003333 QCBORError nError;
3334 QCBORItem Item;
3335
3336 nError = QCBORDecode_GetNext(pMe, &Item);
3337 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003338 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003339 return;
3340 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003341 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003342}
3343
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003344
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003345/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003346 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003347*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003348void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003349{
3350 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003351 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003352
Laurence Lundblade9b334962020-08-27 10:55:53 -07003353 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003354}
3355
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003356
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003357/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003358 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003359*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003360void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3361{
3362 QCBORItem Item;
3363 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3364
Laurence Lundblade9b334962020-08-27 10:55:53 -07003365 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003366}
3367
3368
3369
Laurence Lundblade9b334962020-08-27 10:55:53 -07003370/*
3371 A number of methods decode CBOR that is associated with a
3372 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003373
Laurence Lundblade9b334962020-08-27 10:55:53 -07003374 The API of the method returns the
3375 data in a way specific to the
3376
3377 No tags at all.
3378
3379
3380 Require tag for the particular type for the method and no other.
3381
3382
3383 Either no tags at all or the particular type for the method and no other.
3384
3385 No tag for particular type; pass other tags along.
3386
3387 Require the tag for the particular type; pass other tags along
3388
3389 Any tagging is OK; consume the tag for the particular type if present,
3390 pass other tags along.
3391
3392
3393 1) REQUIRED
3394- 1 XXXX -- works
3395- T 1 XXX -- works, T is returned
3396
3397 if(tag is of interest) {
3398 process content
3399 return T if present
3400 }
3401
3402
3403 2) FORBIDDEN
3404 - XXX -- works
3405 - T XXX -- ???
3406
3407 if(tag is of interest) {
3408 error out since tag is forbidden
3409 } else {
3410 process contents
3411 return T
3412 }
3413
3414 3) OPTIONAL
3415 - XXX works
3416 - 1 XXX works
3417 - T XXX
3418 - T 1 XXX works, T is returned
3419
3420if (inner tag is of interest) {
3421 process content
3422 return tag T if present
3423 } else if (there is no tag) {
3424 process content
3425 } else {
3426 process content if possible
3427 return T
3428 }
3429
3430A field is type X
3431 - tag for type X is REQUIRED
3432 - tag for type X is FORBIDDEN
3433 - tag for type X is optional
3434 - Other tags are FORBIDDEN
3435 - Other tags are ALLOWED
3436
3437
3438
3439 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003440
3441static void ProcessEpochDate(QCBORDecodeContext *pMe,
3442 QCBORItem *pItem,
3443 uint8_t uTagRequirement,
3444 int64_t *pnTime)
3445{
3446 if(pMe->uLastError != QCBOR_SUCCESS) {
3447 // Already in error state, do nothing
3448 return;
3449 }
3450
3451 QCBORError uErr;
3452
3453 const TagSpecification TagSpec =
3454 {
3455 uTagRequirement,
3456 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3457 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3458 };
3459
Laurence Lundblade4b270642020-08-14 12:53:07 -07003460 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003461 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3462 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003463 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003464 if(uErr != QCBOR_SUCCESS) {
3465 goto Done;
3466 }
3467
3468 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3469 uErr = DecodeDateEpoch(pItem);
3470 if(uErr != QCBOR_SUCCESS) {
3471 goto Done;
3472 }
3473 }
3474
Laurence Lundblade9b334962020-08-27 10:55:53 -07003475 // Save the tags in the last item's tags in the decode context
3476 // for QCBORDecode_GetNthTagOfLast()
3477 CopyTags(pMe, pItem);
3478
Laurence Lundbladec7114722020-08-13 05:11:40 -07003479 *pnTime = pItem->val.epochDate.nSeconds;
3480
3481Done:
3482 pMe->uLastError = (uint8_t)uErr;
3483}
3484
3485
3486void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3487 uint8_t uTagRequirement,
3488 int64_t *pnTime)
3489{
3490 if(pMe->uLastError != QCBOR_SUCCESS) {
3491 // Already in error state, do nothing
3492 return;
3493 }
3494
3495 QCBORItem Item;
3496 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3497
3498 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3499}
3500
3501
3502void
3503QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3504 int64_t nLabel,
3505 uint8_t uTagRequirement,
3506 int64_t *pnTime)
3507{
3508 QCBORItem Item;
3509 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3510 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3511}
3512
3513
3514void
3515QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3516 const char *szLabel,
3517 uint8_t uTagRequirement,
3518 int64_t *pnTime)
3519{
3520 QCBORItem Item;
3521 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3522 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3523}
3524
3525
3526
3527
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003528void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3529 TagSpecification TagSpec,
3530 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003531{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003532 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003533 // Already in error state, do nothing
3534 return;
3535 }
3536
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003537 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003538 QCBORItem Item;
3539
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003540 uError = QCBORDecode_GetNext(pMe, &Item);
3541 if(uError != QCBOR_SUCCESS) {
3542 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003543 return;
3544 }
3545
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003546 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003547
3548 if(pMe->uLastError == QCBOR_SUCCESS) {
3549 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003550 } else {
3551 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003552 }
3553}
3554
Laurence Lundbladec4537442020-04-14 18:53:22 -07003555
3556
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003557
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003558static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003559 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003560 UsefulBufC *pValue,
3561 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003562{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003563 const TagSpecification TagSpec =
3564 {
3565 uTagRequirement,
3566 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3567 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3568 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003569
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003570 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003571 if(uErr != QCBOR_SUCCESS) {
3572 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003574
3575 *pValue = pItem->val.string;
3576
3577 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3578 *pbIsNegative = false;
3579 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3580 *pbIsNegative = true;
3581 }
3582
3583 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003584}
3585
3586
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003587/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003588 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003589 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003590void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3591 uint8_t uTagRequirement,
3592 UsefulBufC *pValue,
3593 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003594{
3595 if(pMe->uLastError != QCBOR_SUCCESS) {
3596 // Already in error state, do nothing
3597 return;
3598 }
3599
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003600 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3602 if(uError != QCBOR_SUCCESS) {
3603 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003604 return;
3605 }
3606
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003607 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003608}
3609
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003610
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003611/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003612 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003613*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003614void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3615 int64_t nLabel,
3616 uint8_t uTagRequirement,
3617 UsefulBufC *pValue,
3618 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003619{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003620 QCBORItem Item;
3621 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003622 if(pMe->uLastError != QCBOR_SUCCESS) {
3623 return;
3624 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003625
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003626 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627}
3628
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003629
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003630/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003631 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003632*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003633void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3634 const char *szLabel,
3635 uint8_t uTagRequirement,
3636 UsefulBufC *pValue,
3637 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003638{
3639 QCBORItem Item;
3640 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003641 if(pMe->uLastError != QCBOR_SUCCESS) {
3642 return;
3643 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003644
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003645 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003646}
3647
3648
3649
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003650
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003651// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003652QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3653 const QCBORItem *pItem,
3654 UsefulBufC *pMessage,
3655 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003657 const TagSpecification TagSpecText =
3658 {
3659 uTagRequirement,
3660 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3661 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3662 };
3663 const TagSpecification TagSpecBinary =
3664 {
3665 uTagRequirement,
3666 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3667 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3668 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003669
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003670 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003671
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003672 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003673 *pMessage = pItem->val.string;
3674 if(pbIsNot7Bit != NULL) {
3675 *pbIsNot7Bit = false;
3676 }
3677 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003678 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003679 *pMessage = pItem->val.string;
3680 if(pbIsNot7Bit != NULL) {
3681 *pbIsNot7Bit = true;
3682 }
3683 uReturn = QCBOR_SUCCESS;
3684
3685 } else {
3686 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3687 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003688
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003689 return uReturn;
3690}
3691
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003692// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3693
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003694
3695
3696
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003697#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003698
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003699typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003700
3701
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003702// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003703static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003705 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003706
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003707 if(uResult != 0) {
3708 /* This loop will run a maximum of 19 times because
3709 * UINT64_MAX < 10 ^^ 19. More than that will cause
3710 * exit with the overflow error
3711 */
3712 for(; nExponent > 0; nExponent--) {
3713 if(uResult > UINT64_MAX / 10) {
3714 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3715 }
3716 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003717 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003718
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003719 for(; nExponent < 0; nExponent++) {
3720 uResult = uResult / 10;
3721 if(uResult == 0) {
3722 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3723 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003724 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003725 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003726 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003727
3728 *puResult = uResult;
3729
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003730 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003731}
3732
3733
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003734// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003735static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003736{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003737 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003738
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003739 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003740
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003741 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003742 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003743 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003744 */
3745 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003746 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003747 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003748 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003749 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003750 nExponent--;
3751 }
3752
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003753 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003754 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003755 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3756 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003757 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003758 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003759 }
3760
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003761 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003762
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003763 return QCBOR_SUCCESS;
3764}
3765
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003766
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003767/*
3768 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3769 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003770static inline QCBORError ExponentiateNN(int64_t nMantissa,
3771 int64_t nExponent,
3772 int64_t *pnResult,
3773 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003774{
3775 uint64_t uResult;
3776
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003777 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003778 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003779 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3780
3781 // Do the exponentiation of the positive mantissa
3782 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3783 if(uReturn) {
3784 return uReturn;
3785 }
3786
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003787
Laurence Lundblade983500d2020-05-14 11:49:34 -07003788 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3789 of INT64_MIN. This assumes two's compliment representation where
3790 INT64_MIN is one increment farther from 0 than INT64_MAX.
3791 Trying to write -INT64_MIN doesn't work to get this because the
3792 compiler tries to work with an int64_t which can't represent
3793 -INT64_MIN.
3794 */
3795 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3796
3797 // Error out if too large
3798 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003799 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3800 }
3801
3802 // Casts are safe because of checks above
3803 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3804
3805 return QCBOR_SUCCESS;
3806}
3807
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003808
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003809/*
3810 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3811 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003812static inline QCBORError ExponentitateNU(int64_t nMantissa,
3813 int64_t nExponent,
3814 uint64_t *puResult,
3815 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816{
3817 if(nMantissa < 0) {
3818 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3819 }
3820
3821 // Cast to unsigned is OK because of check for negative
3822 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3823 // Exponentiation is straight forward
3824 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3825}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003826
3827
3828/*
3829 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3830 */
3831static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3832 int64_t nExponent,
3833 uint64_t *puResult,
3834 fExponentiator pfExp)
3835{
3836 return (*pfExp)(uMantissa, nExponent, puResult);
3837}
3838
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003839#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3840
3841
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003842
3843
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003844
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003845static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003846{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003848
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003849 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003850 const uint8_t *pByte = BigNum.ptr;
3851 size_t uLen = BigNum.len;
3852 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003853 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003854 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003855 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003856 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857 }
3858
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003859 *pResult = uResult;
3860 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003861}
3862
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003863
Laurence Lundblade887add82020-05-17 05:50:34 -07003864static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003866 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003867}
3868
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003869
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003870static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003871{
3872 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003873 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3874 if(uError) {
3875 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003876 }
3877 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3878 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003879 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003880}
3881
3882
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003883static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003884{
3885 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003886 /* The negative integer furthest from zero for a C int64_t is
3887 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3888 negative number in CBOR is computed as -n - 1 where n is the
3889 encoded integer, where n is what is in the variable BigNum. When
3890 converting BigNum to a uint64_t, the maximum value is thus
3891 INT64_MAX, so that when it -n - 1 is applied to it the result will
3892 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003893
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003894 -n - 1 <= INT64_MIN.
3895 -n - 1 <= -INT64_MAX - 1
3896 n <= INT64_MAX.
3897 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003898 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003899 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003900 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003901 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003902
3903 /// Now apply -n - 1. The cast is safe because
3904 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3905 // is the largest positive integer that an int64_t can
3906 // represent. */
3907 *pnResult = -(int64_t)uResult - 1;
3908
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003909 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003910}
3911
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003912
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003913
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003914
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003915
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003916/*
3917Convert a integers and floats to an int64_t.
3918
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003919\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003920
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003921\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003922
3923\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3924
3925\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3926
3927*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003928static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003929{
3930 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003931 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003932 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003933#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003934 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003935 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3936 http://www.cplusplus.com/reference/cmath/llround/
3937 */
3938 // Not interested in FE_INEXACT
3939 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003940 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3941 *pnValue = llround(pItem->val.dfnum);
3942 } else {
3943 *pnValue = lroundf(pItem->val.fnum);
3944 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003945 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3946 // llround() shouldn't result in divide by zero, but catch
3947 // it here in case it unexpectedly does. Don't try to
3948 // distinguish between the various exceptions because it seems
3949 // they vary by CPU, compiler and OS.
3950 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003951 }
3952 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003953 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003954 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003955#else
3956 return QCBOR_ERR_HW_FLOAT_DISABLED;
3957#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003958 break;
3959
3960 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003961 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003962 *pnValue = pItem->val.int64;
3963 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003964 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003965 }
3966 break;
3967
3968 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003969 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003970 if(pItem->val.uint64 < INT64_MAX) {
3971 *pnValue = pItem->val.int64;
3972 } else {
3973 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3974 }
3975 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003976 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003977 }
3978 break;
3979
3980 default:
3981 return QCBOR_ERR_UNEXPECTED_TYPE;
3982 }
3983 return QCBOR_SUCCESS;
3984}
3985
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003987void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003988 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003989 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003990 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003992 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003993 return;
3994 }
3995
Laurence Lundbladee6430642020-03-14 21:15:44 -07003996 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003997 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3998 if(uError) {
3999 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004000 return;
4001 }
4002
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004003 if(pItem) {
4004 *pItem = Item;
4005 }
4006
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008}
4009
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004010
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004011void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4012 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004013 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004014 int64_t *pnValue,
4015 QCBORItem *pItem)
4016{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004017 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004018 if(pMe->uLastError != QCBOR_SUCCESS) {
4019 return;
4020 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023}
4024
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004025
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004026void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4027 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004028 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029 int64_t *pnValue,
4030 QCBORItem *pItem)
4031{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004033 if(pMe->uLastError != QCBOR_SUCCESS) {
4034 return;
4035 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004036
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004037 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004038}
4039
4040
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004041/*
4042 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004043
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004044 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004045
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004047
4048 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4049
4050 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4051
4052 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004053static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004054{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 switch(pItem->uDataType) {
4056
4057 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004058 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004059 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004060 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004061 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004062 }
4063 break;
4064
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004065 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004066 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004067 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004068 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004069 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070 }
4071 break;
4072
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004073#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4074 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004075 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004076 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004077 pItem->val.expAndMantissa.nExponent,
4078 pnValue,
4079 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082 }
4083 break;
4084
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004085 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004086 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004088 pItem->val.expAndMantissa.nExponent,
4089 pnValue,
4090 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093 }
4094 break;
4095
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004097 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004098 int64_t nMantissa;
4099 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004100 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4101 if(uErr) {
4102 return uErr;
4103 }
4104 return ExponentiateNN(nMantissa,
4105 pItem->val.expAndMantissa.nExponent,
4106 pnValue,
4107 Exponentitate10);
4108 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004110 }
4111 break;
4112
4113 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004114 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004115 int64_t nMantissa;
4116 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004117 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4118 if(uErr) {
4119 return uErr;
4120 }
4121 return ExponentiateNN(nMantissa,
4122 pItem->val.expAndMantissa.nExponent,
4123 pnValue,
4124 Exponentitate10);
4125 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004126 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 }
4128 break;
4129
4130 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004131 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004132 int64_t nMantissa;
4133 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004134 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4135 if(uErr) {
4136 return uErr;
4137 }
4138 return ExponentiateNN(nMantissa,
4139 pItem->val.expAndMantissa.nExponent,
4140 pnValue,
4141 Exponentitate2);
4142 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004143 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004144 }
4145 break;
4146
4147 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004148 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004149 int64_t nMantissa;
4150 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004151 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4152 if(uErr) {
4153 return uErr;
4154 }
4155 return ExponentiateNN(nMantissa,
4156 pItem->val.expAndMantissa.nExponent,
4157 pnValue,
4158 Exponentitate2);
4159 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004161 }
4162 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004163#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4164
Laurence Lundbladee6430642020-03-14 21:15:44 -07004165
Laurence Lundbladec4537442020-04-14 18:53:22 -07004166 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004167 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004168}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004169
4170
Laurence Lundbladec4537442020-04-14 18:53:22 -07004171/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004172 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004173 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004174void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004175{
4176 QCBORItem Item;
4177
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004178 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004179
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004180 if(pMe->uLastError == QCBOR_SUCCESS) {
4181 // The above conversion succeeded
4182 return;
4183 }
4184
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004185 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004186 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004187 return;
4188 }
4189
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004190 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004191}
4192
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004193
4194/*
4195Public function, see header qcbor/qcbor_decode.h file
4196*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004197void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4198 int64_t nLabel,
4199 uint32_t uConvertTypes,
4200 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201{
4202 QCBORItem Item;
4203
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205
4206 if(pMe->uLastError == QCBOR_SUCCESS) {
4207 // The above conversion succeeded
4208 return;
4209 }
4210
4211 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4212 // The above conversion failed in a way that code below can't correct
4213 return;
4214 }
4215
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004217}
4218
4219
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004220/*
4221Public function, see header qcbor/qcbor_decode.h file
4222*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004223void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4224 const char *szLabel,
4225 uint32_t uConvertTypes,
4226 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004227{
4228 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004229 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004230
4231 if(pMe->uLastError == QCBOR_SUCCESS) {
4232 // The above conversion succeeded
4233 return;
4234 }
4235
4236 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4237 // The above conversion failed in a way that code below can't correct
4238 return;
4239 }
4240
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004241 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004242}
4243
4244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004246{
4247 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004248 case QCBOR_TYPE_DOUBLE:
4249 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004250#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004251 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004252 // Can't use llround here because it will not convert values
4253 // greater than INT64_MAX and less than UINT64_MAX that
4254 // need to be converted so it is more complicated.
4255 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4256 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4257 if(isnan(pItem->val.dfnum)) {
4258 return QCBOR_ERR_FLOAT_EXCEPTION;
4259 } else if(pItem->val.dfnum < 0) {
4260 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4261 } else {
4262 double dRounded = round(pItem->val.dfnum);
4263 // See discussion in DecodeDateEpoch() for
4264 // explanation of - 0x7ff
4265 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4266 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4267 }
4268 *puValue = (uint64_t)dRounded;
4269 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004270 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004271 if(isnan(pItem->val.fnum)) {
4272 return QCBOR_ERR_FLOAT_EXCEPTION;
4273 } else if(pItem->val.fnum < 0) {
4274 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4275 } else {
4276 float fRounded = roundf(pItem->val.fnum);
4277 // See discussion in DecodeDateEpoch() for
4278 // explanation of - 0x7ff
4279 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4280 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4281 }
4282 *puValue = (uint64_t)fRounded;
4283 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004284 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004285 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4286 // round() and roundf() shouldn't result in exceptions here, but
4287 // catch them to be robust and thorough. Don't try to
4288 // distinguish between the various exceptions because it seems
4289 // they vary by CPU, compiler and OS.
4290 return QCBOR_ERR_FLOAT_EXCEPTION;
4291 }
4292
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004293 } else {
4294 return QCBOR_ERR_UNEXPECTED_TYPE;
4295 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004296#else
4297 return QCBOR_ERR_HW_FLOAT_DISABLED;
4298#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004299 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004300
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004301 case QCBOR_TYPE_INT64:
4302 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4303 if(pItem->val.int64 >= 0) {
4304 *puValue = (uint64_t)pItem->val.int64;
4305 } else {
4306 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4307 }
4308 } else {
4309 return QCBOR_ERR_UNEXPECTED_TYPE;
4310 }
4311 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004312
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004313 case QCBOR_TYPE_UINT64:
4314 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4315 *puValue = pItem->val.uint64;
4316 } else {
4317 return QCBOR_ERR_UNEXPECTED_TYPE;
4318 }
4319 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004320
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004321 default:
4322 return QCBOR_ERR_UNEXPECTED_TYPE;
4323 }
4324
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004325 return QCBOR_SUCCESS;
4326}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004327
4328
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004329void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004330 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004331 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004332 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004333{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004334 if(pMe->uLastError != QCBOR_SUCCESS) {
4335 return;
4336 }
4337
Laurence Lundbladec4537442020-04-14 18:53:22 -07004338 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004339
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004340 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4341 if(uError) {
4342 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343 return;
4344 }
4345
Laurence Lundbladea826c502020-05-10 21:07:00 -07004346 if(pItem) {
4347 *pItem = Item;
4348 }
4349
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004350 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004351}
4352
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004353
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004354void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004355 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004356 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357 uint64_t *puValue,
4358 QCBORItem *pItem)
4359{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004360 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004361 if(pMe->uLastError != QCBOR_SUCCESS) {
4362 return;
4363 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004364
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004365 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004366}
4367
4368
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004369void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004371 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372 uint64_t *puValue,
4373 QCBORItem *pItem)
4374{
4375 if(pMe->uLastError != QCBOR_SUCCESS) {
4376 return;
4377 }
4378
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004379 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004380 if(pMe->uLastError != QCBOR_SUCCESS) {
4381 return;
4382 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004383
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004384 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004385}
4386
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004387
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004388/*
4389 Public function, see header qcbor/qcbor_decode.h file
4390*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004391static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004392{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004393 switch(pItem->uDataType) {
4394
4395 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004396 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004397 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4398 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004399 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400 }
4401 break;
4402
4403 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004404 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4406 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004407 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004408 }
4409 break;
4410
4411#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4412
4413 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004414 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004415 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004416 pItem->val.expAndMantissa.nExponent,
4417 puValue,
4418 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004419 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004420 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004421 }
4422 break;
4423
4424 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4427 pItem->val.expAndMantissa.nExponent,
4428 puValue,
4429 Exponentitate2);
4430 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004431 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004432 }
4433 break;
4434
4435 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004437 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004438 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004439 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440 if(uErr != QCBOR_SUCCESS) {
4441 return uErr;
4442 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004443 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004444 pItem->val.expAndMantissa.nExponent,
4445 puValue,
4446 Exponentitate10);
4447 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004448 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 }
4450 break;
4451
4452 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004453 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4455 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004456 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 }
4458 break;
4459
4460 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004462 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004463 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004464 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004465 if(uErr != QCBOR_SUCCESS) {
4466 return uErr;
4467 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004468 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469 pItem->val.expAndMantissa.nExponent,
4470 puValue,
4471 Exponentitate2);
4472 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004473 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 }
4475 break;
4476
4477 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4480 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482 }
4483 break;
4484#endif
4485 default:
4486 return QCBOR_ERR_UNEXPECTED_TYPE;
4487 }
4488}
4489
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004490
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004491/*
4492 Public function, see header qcbor/qcbor_decode.h file
4493*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004494void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004495{
4496 QCBORItem Item;
4497
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004499
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004500 if(pMe->uLastError == QCBOR_SUCCESS) {
4501 // The above conversion succeeded
4502 return;
4503 }
4504
4505 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4506 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004507 return;
4508 }
4509
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004510 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004511}
4512
Laurence Lundbladec4537442020-04-14 18:53:22 -07004513
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004514/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004515 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004517void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004518 int64_t nLabel,
4519 uint32_t uConvertTypes,
4520 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521{
4522 QCBORItem Item;
4523
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004524 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004525
4526 if(pMe->uLastError == QCBOR_SUCCESS) {
4527 // The above conversion succeeded
4528 return;
4529 }
4530
4531 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4532 // The above conversion failed in a way that code below can't correct
4533 return;
4534 }
4535
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004536 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004537}
4538
4539
4540/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004541 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004542*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004543void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004544 const char *szLabel,
4545 uint32_t uConvertTypes,
4546 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004547{
4548 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004550
4551 if(pMe->uLastError == QCBOR_SUCCESS) {
4552 // The above conversion succeeded
4553 return;
4554 }
4555
4556 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4557 // The above conversion failed in a way that code below can't correct
4558 return;
4559 }
4560
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004561 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004562}
4563
4564
Laurence Lundblade9b334962020-08-27 10:55:53 -07004565static QCBORError ConvertDouble(const QCBORItem *pItem,
4566 uint32_t uConvertTypes,
4567 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568{
4569 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004570 case QCBOR_TYPE_FLOAT:
4571#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4572 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4573 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004574 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004575 *pdValue = (double)pItem->val.fnum;
4576 } else {
4577 return QCBOR_ERR_UNEXPECTED_TYPE;
4578 }
4579 }
4580#else
4581 return QCBOR_ERR_HW_FLOAT_DISABLED;
4582#endif
4583 break;
4584
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004585 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004586 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4587 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588 *pdValue = pItem->val.dfnum;
4589 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591 }
4592 }
4593 break;
4594
4595 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004596#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004597 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004598 // A simple cast seems to do the job with no worry of exceptions.
4599 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600 *pdValue = (double)pItem->val.int64;
4601
4602 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004603 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004604 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004605#else
4606 return QCBOR_ERR_HW_FLOAT_DISABLED;
4607#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608 break;
4609
4610 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004611#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004612 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004613 // A simple cast seems to do the job with no worry of exceptions.
4614 // There will be precision loss for some values.
4615 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004617 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618 }
4619 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004620#else
4621 return QCBOR_ERR_HW_FLOAT_DISABLED;
4622#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004623
4624 default:
4625 return QCBOR_ERR_UNEXPECTED_TYPE;
4626 }
4627
4628 return QCBOR_SUCCESS;
4629}
4630
4631
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004632void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004633 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004634 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004635 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004636{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004637 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004638 return;
4639 }
4640
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004641 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004642
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004643 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004644 if(uError) {
4645 pMe->uLastError = (uint8_t)uError;
4646 return;
4647 }
4648
4649 if(pItem) {
4650 *pItem = Item;
4651 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004652
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004653 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004654}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004655
Laurence Lundbladec4537442020-04-14 18:53:22 -07004656
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4658 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004659 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660 double *pdValue,
4661 QCBORItem *pItem)
4662{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004663 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004664 if(pMe->uLastError != QCBOR_SUCCESS) {
4665 return;
4666 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004667
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004668 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004669}
4670
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004671
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004672void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4673 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 double *pdValue,
4676 QCBORItem *pItem)
4677{
4678 if(pMe->uLastError != QCBOR_SUCCESS) {
4679 return;
4680 }
4681
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004682 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004683 if(pMe->uLastError != QCBOR_SUCCESS) {
4684 return;
4685 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004687 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688}
4689
4690
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004691#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004692static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4693{
4694 double dResult;
4695
4696 dResult = 0.0;
4697 const uint8_t *pByte = BigNum.ptr;
4698 size_t uLen = BigNum.len;
4699 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004700 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004701 while(uLen--) {
4702 dResult = (dResult * 256.0) + (double)*pByte++;
4703 }
4704
4705 return dResult;
4706}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004707#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4708
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004709
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004710static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004711{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004712#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004713 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004714 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4715
4716 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004718
4719#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004721 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004722 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4724 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4725 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 }
4728 break;
4729
4730 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004731 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004732 // Underflow gives 0, overflow gives infinity
4733 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4734 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004735 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004736 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 }
4738 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004739#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004740
4741 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004742 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004743 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4744 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746 }
4747 break;
4748
4749 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004750 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004751 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004752 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004753 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754 }
4755 break;
4756
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004757#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004759 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4761 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4762 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004763 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 }
4765 break;
4766
4767 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004768 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4770 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4771 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004772 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004773 }
4774 break;
4775
4776 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4779 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4780 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004781 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004782 }
4783 break;
4784
4785 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004787 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004788 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4789 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004790 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004791 }
4792 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004793#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4794
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 default:
4796 return QCBOR_ERR_UNEXPECTED_TYPE;
4797 }
4798
4799 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004800
4801#else
4802 (void)pItem;
4803 (void)uConvertTypes;
4804 (void)pdValue;
4805 return QCBOR_ERR_HW_FLOAT_DISABLED;
4806#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4807
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808}
4809
4810
4811/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004812 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004813*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004814void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4815 uint32_t uConvertTypes,
4816 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004817{
4818
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004819 QCBORItem Item;
4820
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004821 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004822
4823 if(pMe->uLastError == QCBOR_SUCCESS) {
4824 // The above conversion succeeded
4825 return;
4826 }
4827
4828 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4829 // The above conversion failed in a way that code below can't correct
4830 return;
4831 }
4832
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004833 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004834}
4835
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836
4837/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004838 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004840void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4841 int64_t nLabel,
4842 uint32_t uConvertTypes,
4843 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844{
4845 QCBORItem Item;
4846
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004847 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848
4849 if(pMe->uLastError == QCBOR_SUCCESS) {
4850 // The above conversion succeeded
4851 return;
4852 }
4853
4854 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4855 // The above conversion failed in a way that code below can't correct
4856 return;
4857 }
4858
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860}
4861
4862
4863/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004864 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004866void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4867 const char *szLabel,
4868 uint32_t uConvertTypes,
4869 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870{
4871 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873
4874 if(pMe->uLastError == QCBOR_SUCCESS) {
4875 // The above conversion succeeded
4876 return;
4877 }
4878
4879 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4880 // The above conversion failed in a way that code below can't correct
4881 return;
4882 }
4883
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004884 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004886
4887
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004888
4889
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004890#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004891static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4892{
4893 while((uInt & 0xff00000000000000UL) == 0) {
4894 uInt = uInt << 8;
4895 };
4896
4897 UsefulOutBuf UOB;
4898
4899 UsefulOutBuf_Init(&UOB, Buffer);
4900
4901 while(uInt) {
4902 const uint64_t xx = uInt & 0xff00000000000000UL;
4903 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4904 uInt = uInt << 8;
4905 (void)xx;
4906 }
4907
4908 return UsefulOutBuf_OutUBuf(&UOB);
4909}
4910
4911
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004912static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4913 TagSpecification TagSpec,
4914 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004915{
4916 QCBORError uErr;
4917 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004918 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004919 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004920 if(uErr != QCBOR_SUCCESS) {
4921 goto Done;
4922 }
4923
4924 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4925 break; // Successful exit. Moving on to finish decoding.
4926 }
4927
4928 // The item is an array, which means an undecoded
4929 // mantissa and exponent, so decode it. It will then
4930 // have a different type and exit the loop if.
4931 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4932 if(uErr != QCBOR_SUCCESS) {
4933 goto Done;
4934 }
4935
4936 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004937 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004938 }
4939Done:
4940 return uErr;
4941}
4942
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004943
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004944static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004945 TagSpecification TagSpec,
4946 QCBORItem *pItem,
4947 int64_t *pnMantissa,
4948 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004949{
4950 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004951
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004952 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004953 if(uErr != QCBOR_SUCCESS) {
4954 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004955 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004956
Laurence Lundblade9b334962020-08-27 10:55:53 -07004957 switch (pItem->uDataType) {
4958
4959 case QCBOR_TYPE_DECIMAL_FRACTION:
4960 case QCBOR_TYPE_BIGFLOAT:
4961 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4962 *pnExponent = pItem->val.expAndMantissa.nExponent;
4963 break;
4964
4965 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4966 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4967 *pnExponent = pItem->val.expAndMantissa.nExponent;
4968 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4969 break;
4970
4971 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4972 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4973 *pnExponent = pItem->val.expAndMantissa.nExponent;
4974 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4975 break;
4976
4977 default:
4978 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4979 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004980
4981 Done:
4982 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004983}
4984
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004985
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004986static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004987 TagSpecification TagSpec,
4988 QCBORItem *pItem,
4989 UsefulBuf BufferForMantissa,
4990 UsefulBufC *pMantissa,
4991 bool *pbIsNegative,
4992 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004993{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004994 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004995
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004996 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004997 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004998 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004999 }
5000
5001 uint64_t uMantissa;
5002
5003 switch (pItem->uDataType) {
5004
5005 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005006 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005007 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5008 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5009 *pbIsNegative = false;
5010 } else {
5011 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5012 *pbIsNegative = true;
5013 }
5014 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5015 *pnExponent = pItem->val.expAndMantissa.nExponent;
5016 break;
5017
5018 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005019 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005020 *pnExponent = pItem->val.expAndMantissa.nExponent;
5021 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5022 *pbIsNegative = false;
5023 break;
5024
5025 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005026 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005027 *pnExponent = pItem->val.expAndMantissa.nExponent;
5028 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5029 *pbIsNegative = true;
5030 break;
5031
5032 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005034 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005035
5036Done:
5037 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005038}
5039
5040
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005041/*
5042 Public function, see header qcbor/qcbor_decode.h file
5043*/
5044void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5045 uint8_t uTagRequirement,
5046 int64_t *pnMantissa,
5047 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005049 if(pMe->uLastError != QCBOR_SUCCESS) {
5050 return;
5051 }
5052
5053 QCBORItem Item;
5054 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5055 if(uError) {
5056 pMe->uLastError = (uint8_t)uError;
5057 return;
5058 }
5059
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005060 const TagSpecification TagSpec =
5061 {
5062 uTagRequirement,
5063 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5064 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5065 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005066
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005067 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005068}
5069
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005070
5071/*
5072 Public function, see header qcbor/qcbor_decode.h file
5073*/
5074void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005075 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005076 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005077 int64_t *pnMantissa,
5078 int64_t *pnExponent)
5079{
5080 if(pMe->uLastError != QCBOR_SUCCESS) {
5081 return;
5082 }
5083
5084 QCBORItem Item;
5085 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5086
5087 const TagSpecification TagSpec =
5088 {
5089 uTagRequirement,
5090 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5091 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5092 };
5093
5094 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5095}
5096
5097
5098/*
5099 Public function, see header qcbor/qcbor_decode.h file
5100*/
5101void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005102 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005103 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005104 int64_t *pnMantissa,
5105 int64_t *pnExponent)
5106{
5107 if(pMe->uLastError != QCBOR_SUCCESS) {
5108 return;
5109 }
5110
5111 QCBORItem Item;
5112 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5113
5114 const TagSpecification TagSpec =
5115 {
5116 uTagRequirement,
5117 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5118 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5119 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005120
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005121 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5122}
5123
5124
5125/*
5126 Public function, see header qcbor/qcbor_decode.h file
5127*/
5128void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5129 uint8_t uTagRequirement,
5130 UsefulBuf MantissaBuffer,
5131 UsefulBufC *pMantissa,
5132 bool *pbMantissaIsNegative,
5133 int64_t *pnExponent)
5134{
5135 if(pMe->uLastError != QCBOR_SUCCESS) {
5136 return;
5137 }
5138
5139 QCBORItem Item;
5140 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5141 if(uError) {
5142 pMe->uLastError = (uint8_t)uError;
5143 return;
5144 }
5145
5146 const TagSpecification TagSpec =
5147 {
5148 uTagRequirement,
5149 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5150 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5151 };
5152
5153 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5154}
5155
5156
5157/*
5158 Public function, see header qcbor/qcbor_decode.h file
5159*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005160void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005161 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005162 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005163 UsefulBuf BufferForMantissa,
5164 UsefulBufC *pMantissa,
5165 bool *pbIsNegative,
5166 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005167{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005168 if(pMe->uLastError != QCBOR_SUCCESS) {
5169 return;
5170 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005171
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005172 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005173 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005174 if(pMe->uLastError != QCBOR_SUCCESS) {
5175 return;
5176 }
5177
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005178 const TagSpecification TagSpec =
5179 {
5180 uTagRequirement,
5181 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5182 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5183 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005184
5185 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005186}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005187
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005188
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189/*
5190 Public function, see header qcbor/qcbor_decode.h file
5191*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005192void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005193 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005194 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005195 UsefulBuf BufferForMantissa,
5196 UsefulBufC *pMantissa,
5197 bool *pbIsNegative,
5198 int64_t *pnExponent)
5199{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005200 if(pMe->uLastError != QCBOR_SUCCESS) {
5201 return;
5202 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005203
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005204 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005205 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5206 if(pMe->uLastError != QCBOR_SUCCESS) {
5207 return;
5208 }
5209
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005210 const TagSpecification TagSpec =
5211 {
5212 uTagRequirement,
5213 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5214 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5215 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005216
5217 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5218}
5219
5220
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005221/*
5222 Public function, see header qcbor/qcbor_decode.h file
5223*/
5224void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5225 uint8_t uTagRequirement,
5226 int64_t *pnMantissa,
5227 int64_t *pnExponent)
5228{
5229 if(pMe->uLastError != QCBOR_SUCCESS) {
5230 return;
5231 }
5232
5233 QCBORItem Item;
5234 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5235 if(uError) {
5236 pMe->uLastError = (uint8_t)uError;
5237 return;
5238 }
5239 const TagSpecification TagSpec =
5240 {
5241 uTagRequirement,
5242 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5243 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5244 };
5245
5246 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5247}
5248
5249
5250/*
5251 Public function, see header qcbor/qcbor_decode.h file
5252*/
5253void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005254 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005255 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005256 int64_t *pnMantissa,
5257 int64_t *pnExponent)
5258{
5259 if(pMe->uLastError != QCBOR_SUCCESS) {
5260 return;
5261 }
5262
5263 QCBORItem Item;
5264 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5265 if(pMe->uLastError != QCBOR_SUCCESS) {
5266 return;
5267 }
5268
5269 const TagSpecification TagSpec =
5270 {
5271 uTagRequirement,
5272 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5273 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5274 };
5275
5276 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5277}
5278
5279
5280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
5283void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005285 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005286 int64_t *pnMantissa,
5287 int64_t *pnExponent)
5288{
5289 if(pMe->uLastError != QCBOR_SUCCESS) {
5290 return;
5291 }
5292
5293 QCBORItem Item;
5294 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5295 if(pMe->uLastError != QCBOR_SUCCESS) {
5296 return;
5297 }
5298
5299 const TagSpecification TagSpec =
5300 {
5301 uTagRequirement,
5302 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5303 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5304 };
5305
5306 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5307}
5308
5309
5310/*
5311 Public function, see header qcbor/qcbor_decode.h file
5312*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005313void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5314 uint8_t uTagRequirement,
5315 UsefulBuf MantissaBuffer,
5316 UsefulBufC *pMantissa,
5317 bool *pbMantissaIsNegative,
5318 int64_t *pnExponent)
5319{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005320 if(pMe->uLastError != QCBOR_SUCCESS) {
5321 return;
5322 }
5323
5324 QCBORItem Item;
5325 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5326 if(uError) {
5327 pMe->uLastError = (uint8_t)uError;
5328 return;
5329 }
5330
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005331 const TagSpecification TagSpec =
5332 {
5333 uTagRequirement,
5334 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5335 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5336 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005337
5338 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005339}
5340
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005341
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005342/*
5343 Public function, see header qcbor/qcbor_decode.h file
5344*/
5345void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005346 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005347 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005348 UsefulBuf BufferForMantissa,
5349 UsefulBufC *pMantissa,
5350 bool *pbIsNegative,
5351 int64_t *pnExponent)
5352{
5353 if(pMe->uLastError != QCBOR_SUCCESS) {
5354 return;
5355 }
5356
5357 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005358 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5359 if(pMe->uLastError != QCBOR_SUCCESS) {
5360 return;
5361 }
5362
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005363 const TagSpecification TagSpec =
5364 {
5365 uTagRequirement,
5366 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5367 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5368 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005369
5370 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5371}
5372
5373
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005374/*
5375 Public function, see header qcbor/qcbor_decode.h file
5376*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005377void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005378 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005379 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005380 UsefulBuf BufferForMantissa,
5381 UsefulBufC *pMantissa,
5382 bool *pbIsNegative,
5383 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005384{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005385 if(pMe->uLastError != QCBOR_SUCCESS) {
5386 return;
5387 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005388
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005389 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005390 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5391 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005392 return;
5393 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005394
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005395 const TagSpecification TagSpec =
5396 {
5397 uTagRequirement,
5398 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5399 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5400 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005401
5402 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005403}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005404
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005405#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */