blob: e4bad6006482d8144657b8c7393b3cd75e3f184f [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
39#include <math.h> // For isnan(). TODO: list
40#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053043/*
44 This casts away the const-ness of a pointer, usually so it can be
45 freed or realloced.
46 */
47#define UNCONST_POINTER(ptr) ((void *)(ptr))
48
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050
Laurence Lundblade02625d42020-06-25 14:41:41 -070051inline static bool
52// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
53QCBORItem_IsMapOrArray(const QCBORItem *pMe)
54{
55 const uint8_t uDataType = pMe->uDataType;
56 return uDataType == QCBOR_TYPE_MAP ||
57 uDataType == QCBOR_TYPE_ARRAY ||
58 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
59}
60
61inline static bool
62QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
63{
64 if(!QCBORItem_IsMapOrArray(pMe)){
65 return false;
66 }
67
68 if(pMe->val.uCount != 0) {
69 return false;
70 }
71 return true;
72}
73
74inline static bool
75QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
76{
77 if(!QCBORItem_IsMapOrArray(pMe)){
78 return false;
79 }
80
81 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
82 return false;
83 }
84 return true;
85}
86
87
Laurence Lundbladeee851742020-01-08 08:37:05 -080088/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070089 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080090 ===========================================================================*/
91
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070093 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
94 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070095
Laurence Lundblade9c905e82020-04-25 11:31:38 -070096
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098 */
99
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700100
101inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700102DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700103{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700104 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105 /*
106 Limit in DecodeNesting_Descend against more than
107 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
108 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700109 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110}
111
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700112
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700113inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700115{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700116 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 /*
118 Limit in DecodeNesting_Descend against more than
119 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
120 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700121 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700122}
123
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700124
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700125static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700126DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700127{
128 return pNesting->pCurrentBounded->u.ma.uStartOffset;
129}
130
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700131
Laurence Lundblade085d7952020-07-24 10:26:30 -0700132static inline bool
133DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
134{
135 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
136 return true;
137 } else {
138 return false;
139 }
140}
141
142
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700144DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700146 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700147 return true;
148 } else {
149 return false;
150 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700151}
152
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700153
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700154inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700155DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700156{
157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159 return false;
160 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700161 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700162 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700165 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166 return true;
167}
168
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700169
Laurence Lundblade642282a2020-06-23 12:00:33 -0700170inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700171DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700172{
173 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700174 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700175 return true;
176 }
177 return false;
178}
179
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700180
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700181inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700182{
183 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
184 return true;
185 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700186 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundblade085d7952020-07-24 10:26:30 -0700193inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700196 /*
197 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
198 larger than DecodeNesting_EnterBoundedMode which keeps it less than
199 uin32_t so the cast is safe.
200 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700202
203 if(bIsEmpty) {
204 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
205 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206}
207
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700208
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700209inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700211 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700212}
213
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700215inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700216DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700217{
218 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220 return false;
221 }
222 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224 return false;
225 }
226 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700227 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700230 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252inline static bool
253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700263inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700286inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
294inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700306 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700318inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
326 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700327 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700328 return QCBOR_ERR_BUFFER_TOO_LARGE;
329 }
330
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700331 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700332
333 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700334
335 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700336}
337
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700338
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700340DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700341 uint8_t uQCBORType,
342 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700343{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700345
346 if(uCount == 0) {
347 // Nothing to do for empty definite lenth arrays. They are just are
348 // effectively the same as an item that is not a map or array
349 goto Done;
350 // Empty indefinite length maps and arrays are handled elsewhere
351 }
352
353 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700354 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
355 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
356 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357 goto Done;
358 }
359
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700360 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700362 goto Done;
363 }
364
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700365 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700366 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
367 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700368
369 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370
371Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700372 return uError;;
373}
374
375
376static inline void
377DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
378{
379 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
380}
381
382
383static inline void
384DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
385{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700386 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 pNesting->pCurrentBounded--;
388 if(DecodeNesting_IsCurrentBounded(pNesting)) {
389 break;
390 }
391 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700392}
393
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700394static inline void
395DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
396{
397 pNesting->pCurrent = pNesting->pCurrentBounded;
398}
399
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700400
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700401inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700403 uint32_t uEndOffset,
404 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700406 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700408 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410 goto Done;
411 }
412
Laurence Lundblade02625d42020-06-25 14:41:41 -0700413 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700414 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
415 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700416
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418 pNesting->pCurrentBounded = pNesting->pCurrent;
419
420Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700421 return uError;;
422}
423
Laurence Lundbladed0304932020-06-27 10:59:38 -0700424
425static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700426DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427{
428 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429}
430
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700431
Laurence Lundbladeee851742020-01-08 08:37:05 -0800432inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700433DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700435 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700436 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
437 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438}
439
440
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700441inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700442DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700443{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700444 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700445 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700447}
448
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449
Laurence Lundblade02625d42020-06-25 14:41:41 -0700450static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700451DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700452{
453 *pNesting = *pSave;
454}
455
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700456
Laurence Lundblade02625d42020-06-25 14:41:41 -0700457static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700458DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459{
460 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
461}
462
463
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700466{
467 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
468}
469
470
Laurence Lundblade02625d42020-06-25 14:41:41 -0700471#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700472
473const char *TypeStr(uint8_t type)
474{
475 switch(type) {
476 case QCBOR_TYPE_MAP: return " map";
477 case QCBOR_TYPE_ARRAY: return "array";
478 case QCBOR_TYPE_BYTE_STRING: return " bstr";
479 default: return " --- ";
480 }
481}
482
483static char buf[20]; // Not thread safe, but that is OK
484const char *CountString(uint16_t uCount, uint16_t uTotal)
485{
486 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
487 strcpy(buf, "indefinite");
488 } else {
489 sprintf(buf, "%d/%d", uCount, uTotal);
490 }
491 return buf;
492}
493
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700496{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700497#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700499 szName,
500 (uint32_t)pBuf->cursor,
501 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700502
503 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700504 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700505 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700506 break;
507 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700508
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700509 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700511 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700513
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700514 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700515 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700516 pNesting->pLevels[i].u.bs.uEndOfBstr,
517 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700518
519 } else {
520 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700521 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
522 pNesting->pLevels[i].u.ma.uCountTotal));
523 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
524 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700525 }
526 }
527
528 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700529 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700530 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700531#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700532}
533
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535
Laurence Lundbladeee851742020-01-08 08:37:05 -0800536/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
538
539 The following four functions are pretty wrappers for invocation of
540 the string allocator supplied by the caller.
541
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
Laurence Lundbladeee851742020-01-08 08:37:05 -0800544static inline void
545StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546{
547 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
548}
549
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550// StringAllocator_Reallocate called with pMem NULL is
551// equal to StringAllocator_Allocate()
552static inline UsefulBuf
553StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
554 void *pMem,
555 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556{
557 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
558}
559
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560static inline UsefulBuf
561StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562{
563 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
564}
565
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566static inline void
567StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800568{
569 if(pMe->pfAllocator) {
570 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
571 }
572}
573
574
575
Laurence Lundbladeee851742020-01-08 08:37:05 -0800576/*===========================================================================
577 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800579 See qcbor/qcbor_decode.h for definition of the object
580 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582/*
583 Public function, see header file
584 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800585void QCBORDecode_Init(QCBORDecodeContext *me,
586 UsefulBufC EncodedCBOR,
587 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588{
589 memset(me, 0, sizeof(QCBORDecodeContext));
590 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591 // Don't bother with error check on decode mode. If a bad value is
592 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700593 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700594 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700595 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700596 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700597 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598}
599
600
601/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700602 Public function, see header file
603 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800604void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
605 QCBORStringAllocate pfAllocateFunction,
606 void *pAllocateContext,
607 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700608{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
610 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
611 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700612}
613
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614
615/*
616 Public function, see header file
617 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700618void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700620{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700621 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700622 (void)pMe;
623 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700624}
625
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700626
627/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800628 This decodes the fundamental part of a CBOR data item, the type and
629 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundbladeee851742020-01-08 08:37:05 -0800633 This does the network->host byte order conversion. The conversion
634 here also results in the conversion for floats in addition to that
635 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800636
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700637 This returns:
638 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800639
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800641 tags and floats and length for strings and arrays
642
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800644 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800645
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646 The int type is preferred to uint8_t for some variables as this
647 avoids integer promotions, can reduce code size and makes
648 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700649
650 @retval QCBOR_ERR_UNSUPPORTED
651
652 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800654inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
655 int *pnMajorType,
656 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800657 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700658{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700659 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800660
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700661 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800662 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800663
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800665 const int nTmpMajorType = nInitialByte >> 5;
666 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800667
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800668 // Where the number or argument accumulates
669 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800670
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800671 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700672 // Need to get 1,2,4 or 8 additional argument bytes. Map
673 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800674 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800675
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800676 // Loop getting all the bytes in the argument
677 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800678 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800679 // This shift and add gives the endian conversion
680 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
681 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800683 // The reserved and thus-far unused additional info values
684 nReturn = QCBOR_ERR_UNSUPPORTED;
685 goto Done;
686 } else {
687 // Less than 24, additional info is argument or 31, an indefinite length
688 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800689 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700690 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 if(UsefulInputBuf_GetError(pUInBuf)) {
693 nReturn = QCBOR_ERR_HIT_END;
694 goto Done;
695 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 // All successful if we got here.
698 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800700 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800701 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800702
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700703Done:
704 return nReturn;
705}
706
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800709 CBOR doesn't explicitly specify two's compliment for integers but all
710 CPUs use it these days and the test vectors in the RFC are so. All
711 integers in the CBOR structure are positive and the major type
712 indicates positive or negative. CBOR can express positive integers
713 up to 2^x - 1 where x is the number of bits and negative integers
714 down to 2^x. Note that negative numbers can be one more away from
715 zero than positive. Stdint, as far as I can tell, uses two's
716 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800717
Laurence Lundblade9b334962020-08-27 10:55:53 -0700718 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800719 used carefully here, and in particular why it isn't used in the interface.
720 Also see
721 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
722
723 Int is used for values that need less than 16-bits and would be subject
724 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700725
726 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800728inline static QCBORError
729DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700731 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800732
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
734 if (uNumber <= INT64_MAX) {
735 pDecodedItem->val.int64 = (int64_t)uNumber;
736 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800737
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700738 } else {
739 pDecodedItem->val.uint64 = uNumber;
740 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
743 } else {
744 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800745 // CBOR's representation of negative numbers lines up with the
746 // two-compliment representation. A negative integer has one
747 // more in range than a positive integer. INT64_MIN is
748 // equal to (-INT64_MAX) - 1.
749 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700752 } else {
753 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000754 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755 nReturn = QCBOR_ERR_INT_OVERFLOW;
756 }
757 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800758
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759 return nReturn;
760}
761
762// Make sure #define value line up as DecodeSimple counts on this.
763#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
764#error QCBOR_TYPE_FALSE macro value wrong
765#endif
766
767#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
768#error QCBOR_TYPE_TRUE macro value wrong
769#endif
770
771#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
772#error QCBOR_TYPE_NULL macro value wrong
773#endif
774
775#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
776#error QCBOR_TYPE_UNDEF macro value wrong
777#endif
778
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700779#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
780#error QCBOR_TYPE_BREAK macro value wrong
781#endif
782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
784#error QCBOR_TYPE_DOUBLE macro value wrong
785#endif
786
787#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
788#error QCBOR_TYPE_FLOAT macro value wrong
789#endif
790
791/*
792 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700793
794 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
795
796 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800798inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800799DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700801 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundbladeee851742020-01-08 08:37:05 -0800803 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800804 // above make sure uAdditionalInfo values line up with uDataType values.
805 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
806 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800808 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800809 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
810 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700812 case HALF_PREC_FLOAT:
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700813#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700814 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700815 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700816 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700817 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
818 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700819#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700820 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700821#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700822 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700823 case SINGLE_PREC_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700824 // Single precision is normally returned as a double
825 // since double is widely supported, there is no loss of
826 // precision, it makes it easy for the caller in
827 // most cases and it can be converted back to single
828 // with no loss of precision
829 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700830 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700831 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700832 {
833 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
834#ifndef QCBOR_DISABLE_FLOAT_HW_USE
835 // In the normal case, use HW to convert float to double.
836 pDecodedItem->val.dfnum = (double)f;
837 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700838#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700839 // Use of float HW is disabled, return as a float.
840 pDecodedItem->val.fnum = f;
841 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
842
843 // IEEE754_FloatToDouble() could be used here to return
844 // as a double, but it adds object code and most likely
845 // anyone disabling FLOAT HW use doesn't care about
846 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700847#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700848 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700849 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700850
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700851 case DOUBLE_PREC_FLOAT:
852 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700853 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700854 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700856 case CBOR_SIMPLEV_FALSE: // 20
857 case CBOR_SIMPLEV_TRUE: // 21
858 case CBOR_SIMPLEV_NULL: // 22
859 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700860 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700861 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700863 case CBOR_SIMPLEV_ONEBYTE: // 24
864 if(uNumber <= CBOR_SIMPLE_BREAK) {
865 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700866 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 goto Done;
868 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800869 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 default: // 0-19
873 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800874 /*
875 DecodeTypeAndNumber will make uNumber equal to
876 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
877 safe because the 2, 4 and 8 byte lengths of uNumber are in
878 the double/float cases above
879 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700880 pDecodedItem->val.uSimple = (uint8_t)uNumber;
881 break;
882 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884Done:
885 return nReturn;
886}
887
888
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530890 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700891
892 @retval QCBOR_ERR_HIT_END
893
894 @retval QCBOR_ERR_STRING_ALLOCATE
895
896 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800898inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
899 int nMajorType,
900 uint64_t uStrLen,
901 UsefulInputBuf *pUInBuf,
902 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700904 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800906 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
907 // This check makes the casts to size_t below safe.
908
909 // 4 bytes less than the largest sizeof() so this can be tested by
910 // putting a SIZE_MAX length in the CBOR test input (no one will
911 // care the limit on strings is 4 bytes shorter).
912 if(uStrLen > SIZE_MAX-4) {
913 nReturn = QCBOR_ERR_STRING_TOO_LONG;
914 goto Done;
915 }
916
917 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530918 if(UsefulBuf_IsNULLC(Bytes)) {
919 // Failed to get the bytes for this string item
920 nReturn = QCBOR_ERR_HIT_END;
921 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530923
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800924 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530925 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800926 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530927 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700928 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530929 goto Done;
930 }
931 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800932 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530933 } else {
934 // Normal case with no string allocator
935 pDecodedItem->val.string = Bytes;
936 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800937 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800938 // Cast because ternary operator causes promotion to integer
939 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
940 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530942Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700943 return nReturn;
944}
945
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948
949
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950
951
Laurence Lundbladeee851742020-01-08 08:37:05 -0800952// Make sure the constants align as this is assumed by
953// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
955#error QCBOR_TYPE_ARRAY value not lined up with major type
956#endif
957#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
958#error QCBOR_TYPE_MAP value not lined up with major type
959#endif
960
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700961/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800962 This gets a single data item and decodes it including preceding
963 optional tagging. This does not deal with arrays and maps and nesting
964 except to decode the data item introducing them. Arrays and maps are
965 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800966
Laurence Lundbladeee851742020-01-08 08:37:05 -0800967 Errors detected here include: an array that is too long to decode,
968 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700969
970 @retval QCBOR_ERR_UNSUPPORTED
971
972 @retval QCBOR_ERR_HIT_END
973
974 @retval QCBOR_ERR_INT_OVERFLOW
975
976 @retval QCBOR_ERR_STRING_ALLOCATE
977
978 @retval QCBOR_ERR_STRING_TOO_LONG
979
980 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
981
982 @retval QCBOR_ERR_BAD_TYPE_7
983
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700984 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800985static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
986 QCBORItem *pDecodedItem,
987 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700989 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800990
Laurence Lundbladeee851742020-01-08 08:37:05 -0800991 /*
992 Get the major type and the number. Number could be length of more
993 bytes or the value depending on the major type nAdditionalInfo is
994 an encoding of the length of the uNumber and is needed to decode
995 floats and doubles
996 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800997 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800999 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001001 memset(pDecodedItem, 0, sizeof(QCBORItem));
1002
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001003 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001004
Laurence Lundbladeee851742020-01-08 08:37:05 -08001005 // Error out here if we got into trouble on the type and number. The
1006 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001007 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001009 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundbladeee851742020-01-08 08:37:05 -08001011 // At this point the major type and the value are valid. We've got
1012 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001013 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001014 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1015 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001016 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001017 nReturn = QCBOR_ERR_BAD_INT;
1018 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001019 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001020 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001021 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1024 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001025 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1026 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
1027 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
1028 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +05301029 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001031 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032 }
1033 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1036 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1037 // Record the number of items in the array or map
1038 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
1039 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1040 goto Done;
1041 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001042 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001043 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001045 // type conversion OK because of check above
1046 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001048 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001049 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1050 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001051 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001054 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001055 nReturn = QCBOR_ERR_BAD_INT;
1056 } else {
1057 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001058 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001059 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001061
Laurence Lundbladeee851742020-01-08 08:37:05 -08001062 case CBOR_MAJOR_TYPE_SIMPLE:
1063 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001064 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001066
Laurence Lundbladeee851742020-01-08 08:37:05 -08001067 default:
1068 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001069 nReturn = QCBOR_ERR_UNSUPPORTED;
1070 break;
1071 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073Done:
1074 return nReturn;
1075}
1076
1077
1078
1079/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001080 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001081 individual chunk items together into one QCBORItem using the string
1082 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001083
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301084 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001085
1086 @retval QCBOR_ERR_UNSUPPORTED
1087
1088 @retval QCBOR_ERR_HIT_END
1089
1090 @retval QCBOR_ERR_INT_OVERFLOW
1091
1092 @retval QCBOR_ERR_STRING_ALLOCATE
1093
1094 @retval QCBOR_ERR_STRING_TOO_LONG
1095
1096 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1097
1098 @retval QCBOR_ERR_BAD_TYPE_7
1099
1100 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1101
1102 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104static inline QCBORError
1105GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001107 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001108
1109 // Get pointer to string allocator. First use is to pass it to
1110 // GetNext_Item() when option is set to allocate for *every* string.
1111 // Second use here is to allocate space to coallese indefinite
1112 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001113 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1114 &(me->StringAllocator) :
1115 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001117 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001118 nReturn = GetNext_Item(&(me->InBuf),
1119 pDecodedItem,
1120 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001121 if(nReturn) {
1122 goto Done;
1123 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001124
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301126 // code in this function from here down can be eliminated. Run tests, except
1127 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001129 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001130 const uint8_t uStringType = pDecodedItem->uDataType;
1131 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001132 goto Done; // no need to do any work here on non-string types
1133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001135 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301136 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001137 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301140 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001141 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1143 goto Done;
1144 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001145
Laurence Lundblade4b270642020-08-14 12:53:07 -07001146 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001147 UsefulBufC FullString = NULLUsefulBufC;
1148
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001150 // Get item for next chunk
1151 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001152 // NULL string allocator passed here. Do not need to allocate
1153 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001154 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001156 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001157 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001158
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301159 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001160 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001161 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301163 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001164 break;
1165 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001166
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001167 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301168 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001169 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001170 if(StringChunkItem.uDataType != uStringType ||
1171 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001172 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001173 break;
1174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301176 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001177 // The first time throurgh FullString.ptr is NULL and this is
1178 // equivalent to StringAllocator_Allocate()
1179 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1180 UNCONST_POINTER(FullString.ptr),
1181 FullString.len + StringChunkItem.val.string.len);
1182
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001183 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301184 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001185 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 break;
1187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001188
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001189 // Copy new string chunk at the end of string so far.
1190 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001193 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1194 // Getting the item failed, clean up the allocated memory
1195 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001198Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001199 return nReturn;
1200}
1201
Laurence Lundblade9b334962020-08-27 10:55:53 -07001202static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001203 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001204 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001205 } else if(uTagVal == CBOR_TAG_INVALID16) {
1206 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001209 return me->auMappedTags[x];
1210 }
1211}
1212
Laurence Lundblade9b334962020-08-27 10:55:53 -07001213
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001214/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001215 Gets all optional tag data items preceding a data item that is not an
1216 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001217
1218 @retval QCBOR_ERR_UNSUPPORTED
1219
1220 @retval QCBOR_ERR_HIT_END
1221
1222 @retval QCBOR_ERR_INT_OVERFLOW
1223
1224 @retval QCBOR_ERR_STRING_ALLOCATE
1225
1226 @retval QCBOR_ERR_STRING_TOO_LONG
1227
1228 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1229
1230 @retval QCBOR_ERR_BAD_TYPE_7
1231
1232 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1233
1234 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1235
1236 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001237 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001238static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001240{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001241 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1242 CBOR_TAG_INVALID16,
1243 CBOR_TAG_INVALID16,
1244 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001245
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 QCBORError uReturn = QCBOR_SUCCESS;
1247
Laurence Lundblade59289e52019-12-30 13:44:37 -08001248 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001249 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001250 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1251 if(uErr != QCBOR_SUCCESS) {
1252 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001253 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001254 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001255
Laurence Lundblade9b334962020-08-27 10:55:53 -07001256 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001257 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001258 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001259 break;
1260 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001261
Laurence Lundblade9b334962020-08-27 10:55:53 -07001262 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1263 // No room in the tag list
1264 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1265 // Continue on to get all tags on this item even though
1266 // it is erroring out in the end. This is a resource limit
1267 // error, not an problem with being well-formed CBOR.
1268 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001269 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001270 // Slide tags over one in the array to make room at index 0
1271 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1272 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001274
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001275 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001276 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001277 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001278 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001279 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001280 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281 break;
1282 }
1283 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1284 break;
1285 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001286 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001287 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1288 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001289 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1290 // Continue on to get all tags on this item even though
1291 // it is erroring out in the end. This is a resource limit
1292 // error, not an problem with being well-formed CBOR.
1293 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001294 }
1295
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001296 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001297 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001298 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001299
1300 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001301 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001302 }
1303 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001305Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001306 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001307}
1308
1309
1310/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001311 This layer takes care of map entries. It combines the label and data
1312 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001313
1314 @retval QCBOR_ERR_UNSUPPORTED
1315
1316 @retval QCBOR_ERR_HIT_END
1317
1318 @retval QCBOR_ERR_INT_OVERFLOW
1319
1320 @retval QCBOR_ERR_STRING_ALLOCATE
1321
1322 @retval QCBOR_ERR_STRING_TOO_LONG
1323
1324 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1325
1326 @retval QCBOR_ERR_BAD_TYPE_7
1327
1328 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1329
1330 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1331
1332 @retval QCBOR_ERR_TOO_MANY_TAGS
1333
1334 @retval QCBOR_ERR_MAP_LABEL_TYPE
1335
1336 @retval QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001337 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001338static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001339GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001340{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001341 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001342 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001343 if(nReturn)
1344 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001345
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001346 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001347 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001348 goto Done;
1349 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001350
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001351 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1352 // In a map and caller wants maps decoded, not treated as arrays
1353
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001354 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001355 // If in a map and the right decoding mode, get the label
1356
Laurence Lundbladeee851742020-01-08 08:37:05 -08001357 // Save label in pDecodedItem and get the next which will
1358 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001359 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001360 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001361 if(nReturn)
1362 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001363
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301364 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001365
1366 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1367 // strings are always good labels
1368 pDecodedItem->label.string = LabelItem.val.string;
1369 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1370 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001371 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001372 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1373 goto Done;
1374 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1375 pDecodedItem->label.int64 = LabelItem.val.int64;
1376 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1377 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1378 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1379 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1380 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1381 pDecodedItem->label.string = LabelItem.val.string;
1382 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1383 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1384 } else {
1385 // label is not an int or a string. It is an arrray
1386 // or a float or such and this implementation doesn't handle that.
1387 // Also, tags on labels are ignored.
1388 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1389 goto Done;
1390 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001391 }
1392 } else {
1393 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001394 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1395 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1396 goto Done;
1397 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001398 // Decoding a map as an array
1399 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001400 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1401 // Cast is needed because of integer promotion
1402 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001403 }
1404 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001405
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001406Done:
1407 return nReturn;
1408}
1409
1410
Laurence Lundblade02625d42020-06-25 14:41:41 -07001411/*
1412 See if next item is a CBOR break. If it is, it is consumed,
1413 if not it is not consumed.
1414*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001415static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001416NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1417{
1418 *pbNextIsBreak = false;
1419 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001420 QCBORItem Peek;
1421 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1422 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1423 if(uReturn != QCBOR_SUCCESS) {
1424 return uReturn;
1425 }
1426 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001427 // It is not a break, rewind so it can be processed normally.
1428 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001429 } else {
1430 *pbNextIsBreak = true;
1431 }
1432 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001433
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001434 return QCBOR_SUCCESS;
1435}
1436
1437
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001438/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001439 An item was just consumed, now figure out if it was the
1440 end of an array or map that can be closed out. That
1441 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001442*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001443static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001444{
1445 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001446
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447 /* This loops ascending nesting levels as long as there is ascending to do */
1448 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1449
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001450 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001451 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001452 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1453 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 break;
1456 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001459 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001460 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001461 bool bIsBreak = false;
1462 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1463 if(uReturn != QCBOR_SUCCESS) {
1464 goto Done;
1465 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001466
1467 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001468 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001469 break;
1470 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001471
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001472 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001473 /*
1474 Break occurred inside a bstr-wrapped CBOR or
1475 in the top level sequence. This is always an
1476 error because neither are an indefinte length
1477 map/array.
1478 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001479 uReturn = QCBOR_ERR_BAD_BREAK;
1480 goto Done;
1481 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001482
Laurence Lundblade02625d42020-06-25 14:41:41 -07001483 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001484 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001485
Laurence Lundblade02625d42020-06-25 14:41:41 -07001486 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001487
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001488 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001489 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001490 /* 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 -07001491 if(bMarkEnd) {
1492 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001493 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001494
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001495 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001496 break;
1497 }
1498
1499 /* Finally, actually ascend one level. */
1500 DecodeNesting_Ascend(&(pMe->nesting));
1501 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001502
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001503 uReturn = QCBOR_SUCCESS;
1504
1505Done:
1506 return uReturn;
1507}
1508
1509
1510/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001511 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001512 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1513 indefinte length maps and arrays by looking at the item count or
1514 finding CBOR breaks. It detects the ends of the top-level sequence
1515 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001516
1517 @retval QCBOR_ERR_UNSUPPORTED X
1518
1519 @retval QCBOR_ERR_HIT_END
1520
1521 @retval QCBOR_ERR_INT_OVERFLOW X
1522
1523 @retval QCBOR_ERR_STRING_ALLOCATE
1524
1525 @retval QCBOR_ERR_STRING_TOO_LONG
1526
1527 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1528
1529 @retval QCBOR_ERR_BAD_TYPE_7 X
1530
1531 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1532
1533 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1534
1535 @retval QCBOR_ERR_TOO_MANY_TAGS
1536
1537 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1538
1539 @retval QCBOR_ERR_ARRAY_TOO_LONG
1540
1541 @retval QCBOR_ERR_NO_MORE_ITEMS
1542
1543 @retval QCBOR_ERR_BAD_BREAK
1544
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001545 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001546static QCBORError
1547QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001548{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001549 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001550 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001551
Laurence Lundblade642282a2020-06-23 12:00:33 -07001552 /*
1553 If out of bytes to consume, it is either the end of the top-level
1554 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001555
Laurence Lundblade642282a2020-06-23 12:00:33 -07001556 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1557 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1558 CBOR is exited, the length is set back to the top-level's length
1559 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001561 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001562 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001563 goto Done;
1564 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001565
Laurence Lundblade642282a2020-06-23 12:00:33 -07001566 /*
1567 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001568 array. The check for the end of an indefinite length array is
1569 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001570 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001571 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001572 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001573 goto Done;
1574 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001575
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001576 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001577 uReturn = GetNext_MapEntry(me, pDecodedItem);
1578 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001579 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001580 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301581
Laurence Lundblade642282a2020-06-23 12:00:33 -07001582 /*
1583 Breaks ending arrays/maps are always processed at the end of this
1584 function. They should never show up here.
1585 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301586 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001587 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301588 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301589 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001590
Laurence Lundblade642282a2020-06-23 12:00:33 -07001591 /*
1592 Record the nesting level for this data item before processing any
1593 of decrementing and descending.
1594 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001595 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001596
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001598 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001599 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001600 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001601 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001602
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001603 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001604 of in the next chunk of code.
1605
1606 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607 encloses them so a decrement needs to be done for them too, but
1608 that is done only when all the items in them have been
1609 processed, not when they are opened with the exception of an
1610 empty map or array.
1611 */
1612 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1613 pDecodedItem->uDataType,
1614 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001615 if(uReturn != QCBOR_SUCCESS) {
1616 goto Done;
1617 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001618 }
1619
Laurence Lundblade02625d42020-06-25 14:41:41 -07001620 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1621 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1622 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001623 /*
1624 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001625 - A non-aggregate like an integer or string
1626 - An empty definite length map or array
1627 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001628
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001629 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001630 definite length map/array and break detection for an indefinite
1631 length map/array. If the end of the map/array was reached, then
1632 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001633 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001634 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001635 if(uReturn) {
1636 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001637 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301638 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001639
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001640 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001641 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001642 Tell the caller what level is next. This tells them what
1643 maps/arrays were closed out and makes it possible for them to
1644 reconstruct the tree with just the information returned in
1645 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001646 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001647 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001648 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001649 pDecodedItem->uNextNestLevel = 0;
1650 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001651 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001652 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001654Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001655 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001656 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001657 memset(pDecodedItem, 0, sizeof(QCBORItem));
1658 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001659 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001660}
1661
Laurence Lundblade9b334962020-08-27 10:55:53 -07001662static void ShiftTags(QCBORItem *pDecodedItem)
1663{
1664 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1665 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1666 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1667 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1668}
1669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001670
Laurence Lundblade59289e52019-12-30 13:44:37 -08001671/*
1672 Mostly just assign the right data type for the date string.
1673 */
1674inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1675{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1677 return QCBOR_ERR_BAD_OPT_TAG;
1678 }
1679
1680 const UsefulBufC Temp = pDecodedItem->val.string;
1681 pDecodedItem->val.dateString = Temp;
1682 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001683 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001684 return QCBOR_SUCCESS;
1685}
1686
1687
Laurence Lundblade9b334962020-08-27 10:55:53 -07001688
Laurence Lundblade59289e52019-12-30 13:44:37 -08001689/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001690 The epoch formatted date. Turns lots of different forms of encoding
1691 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001693static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001695 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001696
1697 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1698
1699 switch (pDecodedItem->uDataType) {
1700
1701 case QCBOR_TYPE_INT64:
1702 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1703 break;
1704
1705 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001706 // This only happens for CBOR type 0 > INT64_MAX so it is
1707 // always an overflow.
1708 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1709 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710 break;
1711
1712 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001713 case QCBOR_TYPE_FLOAT:
1714#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001715 {
1716 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001717 // conversion to an int64_t to be able to detect doubles that
1718 // are too large to fit into an int64_t. A double has 52
1719 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1720 // to a double actually causes a round up which is bad and
1721 // wrong for the comparison because it will allow conversion
1722 // of doubles that can't fit into a uint64_t. To remedy this
1723 // INT64_MAX - 0x7ff is used as the cutoff point because if
1724 // that value rounds up in conversion to double it will still
1725 // be less than INT64_MAX. 0x7ff is picked because it has 11
1726 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001727 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001728 // INT64_MAX seconds is on the order of 10 billion years, and
1729 // the earth is less than 5 billion years old, so for most
1730 // uses this conversion error won't occur even though doubles
1731 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001732 //
1733 // Without the 0x7ff there is a ~30 minute range of time
1734 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001735 // where this code would go wrong. Some compilers
1736 // will generate warnings or errors without the 0x7ff
1737 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001738 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1739 pDecodedItem->val.dfnum :
1740 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001741 if(isnan(d) ||
1742 d > (double)(INT64_MAX - 0x7ff) ||
1743 d < (double)(INT64_MIN + 0x7ff)) {
1744 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001745 goto Done;
1746 }
1747 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001748 pDecodedItem->val.epochDate.fSecondsFraction =
1749 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001750 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001751#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001752
Laurence Lundbladec7114722020-08-13 05:11:40 -07001753 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001754 goto Done;
1755
Laurence Lundblade9682a532020-06-06 18:33:04 -07001756#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001757 break;
1758
1759 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001760 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001761 goto Done;
1762 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001763
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1765
1766Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001767 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001768}
1769
1770
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001771/*
1772 Mostly just assign the right data type for the bignum.
1773 */
1774inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1775{
1776 // Stack Use: UsefulBuf 1 -- 16
1777 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1778 return QCBOR_ERR_BAD_OPT_TAG;
1779 }
1780 const UsefulBufC Temp = pDecodedItem->val.string;
1781 pDecodedItem->val.bigNum = Temp;
1782 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1783 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1784 : QCBOR_TYPE_NEGBIGNUM);
1785 return QCBOR_SUCCESS;
1786}
1787
1788
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1790/*
1791 Decode decimal fractions and big floats.
1792
1793 When called pDecodedItem must be the array that is tagged as a big
1794 float or decimal fraction, the array that has the two members, the
1795 exponent and mantissa.
1796
1797 This will fetch and decode the exponent and mantissa and put the
1798 result back into pDecodedItem.
1799 */
1800inline static QCBORError
1801QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1802{
1803 QCBORError nReturn;
1804
1805 // --- Make sure it is an array; track nesting level of members ---
1806 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1807 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1808 goto Done;
1809 }
1810
1811 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001812 // definite length arrays, but not for indefnite. Instead remember
1813 // the nesting level the two integers must be at, which is one
1814 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001815 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1816
1817 // --- Is it a decimal fraction or a bigfloat? ---
1818 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1819 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1820
1821 // --- Get the exponent ---
1822 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001823 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001824 if(nReturn != QCBOR_SUCCESS) {
1825 goto Done;
1826 }
1827 if(exponentItem.uNestingLevel != nNestLevel) {
1828 // Array is empty or a map/array encountered when expecting an int
1829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
1832 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1833 // Data arriving as an unsigned int < INT64_MAX has been converted
1834 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1835 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1836 // will be too large for this to handle and thus an error that will
1837 // get handled in the next else.
1838 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1839 } else {
1840 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1841 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1842 goto Done;
1843 }
1844
1845 // --- Get the mantissa ---
1846 QCBORItem mantissaItem;
1847 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1848 if(nReturn != QCBOR_SUCCESS) {
1849 goto Done;
1850 }
1851 if(mantissaItem.uNestingLevel != nNestLevel) {
1852 // Mantissa missing or map/array encountered when expecting number
1853 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1854 goto Done;
1855 }
1856 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1857 // Data arriving as an unsigned int < INT64_MAX has been converted
1858 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1859 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1860 // will be too large for this to handle and thus an error that
1861 // will get handled in an else below.
1862 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1863 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1864 // Got a good big num mantissa
1865 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1866 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001867 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1868 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1869 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001870 } else {
1871 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1872 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1873 goto Done;
1874 }
1875
1876 // --- Check that array only has the two numbers ---
1877 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001878 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001879 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1880 goto Done;
1881 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001882 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001883
1884Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001885 return nReturn;
1886}
1887#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1888
1889
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001890inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1891{
1892 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1893 return QCBOR_ERR_BAD_OPT_TAG;
1894 }
1895 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1896 return QCBOR_SUCCESS;
1897}
1898
1899
1900inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1901{
1902 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1903 return QCBOR_ERR_BAD_OPT_TAG;
1904 }
1905 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001906
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001907 return QCBOR_SUCCESS;
1908}
1909
1910
1911inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1912{
1913 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1914 return QCBOR_ERR_BAD_OPT_TAG;
1915 }
1916 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001917
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001918 return QCBOR_SUCCESS;
1919}
1920
1921
1922inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1923{
1924 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1925 return QCBOR_ERR_BAD_OPT_TAG;
1926 }
1927 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001928
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001929 return QCBOR_SUCCESS;
1930}
1931
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001932
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001933inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1934{
1935 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1936 return QCBOR_ERR_BAD_OPT_TAG;
1937 }
1938 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001939
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001940 return QCBOR_SUCCESS;
1941}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001942
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001943
1944inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1945{
1946 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1947 return QCBOR_ERR_BAD_OPT_TAG;
1948 }
1949 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001950
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001951 return QCBOR_SUCCESS;
1952}
1953
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001954
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001955inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1956{
1957 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1958 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001959 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001960 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1961 } else {
1962 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001963
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001964 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001965
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001966 return QCBOR_SUCCESS;
1967}
1968
1969
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001970inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1971{
1972 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1973 return QCBOR_ERR_BAD_OPT_TAG;
1974 }
1975 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001976
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001977 return QCBOR_SUCCESS;
1978}
1979
1980
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001982 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001983 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001984QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001985QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986{
1987 QCBORError nReturn;
1988
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001989 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001990 if(nReturn != QCBOR_SUCCESS) {
1991 goto Done;
1992 }
1993
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001994 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001995 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001997 // Many of the functions here only just map a CBOR tag to
1998 // a QCBOR_TYPE for a string and could probably be
1999 // implemented with less object code. This implementation
2000 // of string types takes about 120 bytes of object code
2001 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002002 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003 nReturn = DecodeDateString(pDecodedItem);
2004 break;
2005
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002006 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007 nReturn = DecodeDateEpoch(pDecodedItem);
2008 break;
2009
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002010 case CBOR_TAG_POS_BIGNUM:
2011 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002012 nReturn = DecodeBigNum(pDecodedItem);
2013 break;
2014
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002015 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2016 case CBOR_TAG_DECIMAL_FRACTION:
2017 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018 // For aggregate tagged types, what goes into pTags is only collected
2019 // from the surrounding data item, not the contents, so pTags is not
2020 // passed on here.
2021
2022 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
2023 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002024 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002026 case CBOR_TAG_CBOR:
2027 nReturn = DecodeWrappedCBOR(pDecodedItem);
2028 break;
2029
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002030 case CBOR_TAG_CBOR_SEQUENCE:
2031 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
2032 break;
2033
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002034 case CBOR_TAG_URI:
2035 nReturn = DecodeURI(pDecodedItem);
2036 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002037
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002038 case CBOR_TAG_B64URL:
2039 nReturn = DecodeB64URL(pDecodedItem);
2040 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002041
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002042 case CBOR_TAG_B64:
2043 nReturn = DecodeB64(pDecodedItem);
2044 break;
2045
2046 case CBOR_TAG_MIME:
2047 case CBOR_TAG_BINARY_MIME:
2048 nReturn = DecodeMIME(pDecodedItem);
2049 break;
2050
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002051 case CBOR_TAG_REGEX:
2052 nReturn = DecodeRegex(pDecodedItem);
2053 break;
2054
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002055 case CBOR_TAG_BIN_UUID:
2056 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002057 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002058
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002059 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002060 // The end of the tag list or no tags
2061 // Successful exit from the loop.
2062 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002063
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002064 default:
2065 // A tag that is not understood
2066 // A successful exit from the loop
2067 goto Done;
2068
2069 }
2070 if(nReturn != QCBOR_SUCCESS) {
2071 goto Done;
2072 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002073 // A tag was successfully processed, shift it
2074 // out of the list of tags returned.
2075 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076 }
2077
2078Done:
2079 if(nReturn != QCBOR_SUCCESS) {
2080 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2081 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2082 }
2083 return nReturn;
2084}
2085
2086
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002087QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2088{
2089 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2090
2091 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2092
2093 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07002094 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002095
2096 return uErr;
2097}
2098
2099
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002101 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002103QCBORError
2104QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2105 QCBORItem *pDecodedItem,
2106 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002107{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002108 QCBORError nReturn;
2109
2110 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2111 if(nReturn != QCBOR_SUCCESS) {
2112 return nReturn;
2113 }
2114
2115 if(pTags != NULL) {
2116 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002117 // Reverse the order because pTags is reverse of
2118 // QCBORItem.uTags.
2119 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002120 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002121 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002122 }
2123 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2124 return QCBOR_ERR_TOO_MANY_TAGS;
2125 }
2126 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2127 pTags->uNumUsed++;
2128 }
2129 }
2130
2131 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002132}
2133
2134
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002135/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302136 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302137 next one down. If a layer has no work to do for a particular item
2138 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002139
Laurence Lundblade59289e52019-12-30 13:44:37 -08002140 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2141 tagged data items, turning them into the local C representation.
2142 For the most simple it is just associating a QCBOR_TYPE with the data. For
2143 the complex ones that an aggregate of data items, there is some further
2144 decoding and a little bit of recursion.
2145
2146 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302147 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302148 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002149 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002150
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302151 - GetNext_MapEntry -- This handles the combining of two
2152 items, the label and the data, that make up a map entry.
2153 It only does work on maps. It combines the label and data
2154 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002155
Laurence Lundblade59289e52019-12-30 13:44:37 -08002156 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2157 tags into bit flags associated with the data item. No actual decoding
2158 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002159
Laurence Lundblade59289e52019-12-30 13:44:37 -08002160 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302161 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302162 string allocater to create contiguous space for the item. It
2163 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002164
Laurence Lundblade59289e52019-12-30 13:44:37 -08002165 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2166 atomic data item has a "major type", an integer "argument" and optionally
2167 some content. For text and byte strings, the content is the bytes
2168 that make up the string. These are the smallest data items that are
2169 considered to be well-formed. The content may also be other data items in
2170 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002171
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002172 Roughly this takes 300 bytes of stack for vars. Need to
2173 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002174
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302175 */
2176
2177
2178/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002179 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002180 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002181bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002182 const QCBORItem *pItem,
2183 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002184{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002185 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002186 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002187 break;
2188 }
2189 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002190 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002191 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002194 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002195}
2196
2197
2198/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002199 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002200 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002201QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002202{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002203 QCBORError uReturn = me->uLastError;
2204
2205 if(uReturn != QCBOR_SUCCESS) {
2206 goto Done;
2207 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002208
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002209 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002210 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002211 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002212 goto Done;
2213 }
2214
2215 // Error out if not all the bytes are consumed
2216 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002217 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002218 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002219
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002220Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302221 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002222 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002223 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundblade085d7952020-07-24 10:26:30 -07002225 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002226}
2227
2228
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002229/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002230 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002231*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002232// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002233uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2234 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002235 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002236{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002237 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2238 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002239 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002240 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002241 }
2242}
2243
Laurence Lundblade9b334962020-08-27 10:55:53 -07002244/*
2245 Public function, see header qcbor/qcbor_decode.h file
2246*/
2247uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2248 uint32_t uIndex)
2249{
2250 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2251 return CBOR_TAG_INVALID64;
2252 } else {
2253 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2254 }
2255}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002256
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257/*
2258
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002259Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002260
Laurence Lundbladeee851742020-01-08 08:37:05 -08002261 - Hit end of input before it was expected while decoding type and
2262 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002263
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002264 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002265
Laurence Lundbladeee851742020-01-08 08:37:05 -08002266 - Hit end of input while decoding a text or byte string
2267 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002268
Laurence Lundbladeee851742020-01-08 08:37:05 -08002269 - Encountered conflicting tags -- e.g., an item is tagged both a date
2270 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271
Laurence Lundbladeee851742020-01-08 08:37:05 -08002272 - Encontered an array or mapp that has too many items
2273 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275 - Encountered array/map nesting that is too deep
2276 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002277
Laurence Lundbladeee851742020-01-08 08:37:05 -08002278 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2279 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002280
Laurence Lundbladeee851742020-01-08 08:37:05 -08002281 - The type of a map label is not a string or int
2282 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002283
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002284 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002285
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002286 */
2287
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002288
2289
Laurence Lundbladef6531662018-12-04 10:42:22 +09002290
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002291/* ===========================================================================
2292 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002293
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002294 This implements a simple sting allocator for indefinite length
2295 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2296 implements the function type QCBORStringAllocate and allows easy
2297 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002298
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002299 This particular allocator is built-in for convenience. The caller
2300 can implement their own. All of this following code will get
2301 dead-stripped if QCBORDecode_SetMemPool() is not called.
2302
2303 This is a very primitive memory allocator. It does not track
2304 individual allocations, only a high-water mark. A free or
2305 reallocation must be of the last chunk allocated.
2306
2307 The size of the pool and offset to free memory are packed into the
2308 first 8 bytes of the memory pool so we don't have to keep them in
2309 the decode context. Since the address of the pool may not be
2310 aligned, they have to be packed and unpacked as if they were
2311 serialized data of the wire or such.
2312
2313 The sizes packed in are uint32_t to be the same on all CPU types
2314 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002315 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002316
2317
Laurence Lundbladeee851742020-01-08 08:37:05 -08002318static inline int
2319MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002320{
2321 // Use of UsefulInputBuf is overkill, but it is convenient.
2322 UsefulInputBuf UIB;
2323
Laurence Lundbladeee851742020-01-08 08:37:05 -08002324 // Just assume the size here. It was checked during SetUp so
2325 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002326 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2327 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2328 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2329 return UsefulInputBuf_GetError(&UIB);
2330}
2331
2332
Laurence Lundbladeee851742020-01-08 08:37:05 -08002333static inline int
2334MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002335{
2336 // Use of UsefulOutBuf is overkill, but convenient. The
2337 // length check performed here is useful.
2338 UsefulOutBuf UOB;
2339
2340 UsefulOutBuf_Init(&UOB, Pool);
2341 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2342 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2343 return UsefulOutBuf_GetError(&UOB);
2344}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002345
2346
2347/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002348 Internal function for an allocation, reallocation free and destuct.
2349
2350 Having only one function rather than one each per mode saves space in
2351 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002352
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002353 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2354 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002355static UsefulBuf
2356MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002357{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002358 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002359
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002360 uint32_t uPoolSize;
2361 uint32_t uFreeOffset;
2362
2363 if(uNewSize > UINT32_MAX) {
2364 // This allocator is only good up to 4GB. This check should
2365 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2366 goto Done;
2367 }
2368 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2369
2370 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2371 goto Done;
2372 }
2373
2374 if(uNewSize) {
2375 if(pMem) {
2376 // REALLOCATION MODE
2377 // Calculate pointer to the end of the memory pool. It is
2378 // assumed that pPool + uPoolSize won't wrap around by
2379 // assuming the caller won't pass a pool buffer in that is
2380 // not in legitimate memory space.
2381 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2382
2383 // Check that the pointer for reallocation is in the range of the
2384 // pool. This also makes sure that pointer math further down
2385 // doesn't wrap under or over.
2386 if(pMem >= pPool && pMem < pPoolEnd) {
2387 // Offset to start of chunk for reallocation. This won't
2388 // wrap under because of check that pMem >= pPool. Cast
2389 // is safe because the pool is always less than UINT32_MAX
2390 // because of check in QCBORDecode_SetMemPool().
2391 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2392
2393 // Check to see if the allocation will fit. uPoolSize -
2394 // uMemOffset will not wrap under because of check that
2395 // pMem is in the range of the uPoolSize by check above.
2396 if(uNewSize <= uPoolSize - uMemOffset) {
2397 ReturnValue.ptr = pMem;
2398 ReturnValue.len = uNewSize;
2399
2400 // Addition won't wrap around over because uNewSize was
2401 // checked to be sure it is less than the pool size.
2402 uFreeOffset = uMemOffset + uNewSize32;
2403 }
2404 }
2405 } else {
2406 // ALLOCATION MODE
2407 // uPoolSize - uFreeOffset will not underflow because this
2408 // pool implementation makes sure uFreeOffset is always
2409 // smaller than uPoolSize through this check here and
2410 // reallocation case.
2411 if(uNewSize <= uPoolSize - uFreeOffset) {
2412 ReturnValue.len = uNewSize;
2413 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002414 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002415 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002416 }
2417 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002418 if(pMem) {
2419 // FREE MODE
2420 // Cast is safe because of limit on pool size in
2421 // QCBORDecode_SetMemPool()
2422 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2423 } else {
2424 // DESTRUCT MODE
2425 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002426 }
2427 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002428
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002429 UsefulBuf Pool = {pPool, uPoolSize};
2430 MemPool_Pack(Pool, uFreeOffset);
2431
2432Done:
2433 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002434}
2435
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002436
Laurence Lundbladef6531662018-12-04 10:42:22 +09002437/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002438 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002439 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002440QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2441 UsefulBuf Pool,
2442 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002443{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002444 // The pool size and free mem offset are packed into the beginning
2445 // of the pool memory. This compile time check make sure the
2446 // constant in the header is correct. This check should optimize
2447 // down to nothing.
2448 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002449 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002450 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002451
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002452 // The pool size and free offset packed in to the beginning of pool
2453 // memory are only 32-bits. This check will optimize out on 32-bit
2454 // machines.
2455 if(Pool.len > UINT32_MAX) {
2456 return QCBOR_ERR_BUFFER_TOO_LARGE;
2457 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002458
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002459 // This checks that the pool buffer given is big enough.
2460 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2461 return QCBOR_ERR_BUFFER_TOO_SMALL;
2462 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002463
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002464 pMe->StringAllocator.pfAllocator = MemPool_Function;
2465 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2466 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002467
Laurence Lundblade30816f22018-11-10 13:40:22 +07002468 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002469}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002470
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002471
2472
Laurence Lundblade9b334962020-08-27 10:55:53 -07002473static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2474{
2475 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2476}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002477
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478
2479/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002480 Consume an entire map or array (and do next to
2481 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002482 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002483static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002484ConsumeItem(QCBORDecodeContext *pMe,
2485 const QCBORItem *pItemToConsume,
2486 uint_fast8_t *puNextNestLevel)
2487{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002488 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002489 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002490
Laurence Lundblade02625d42020-06-25 14:41:41 -07002491 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002492
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002493 // If it is a map or array, this will tell if it is empty.
2494 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2495
2496 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2497 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002498
Laurence Lundblade1341c592020-04-11 14:19:05 -07002499 /* This works for definite and indefinite length
2500 * maps and arrays by using the nesting level
2501 */
2502 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002503 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade4b270642020-08-14 12:53:07 -07002504 if( QCBORDecode_IsNotWellFormed(uReturn)) {
2505 // TODO: also resource limit errors
Laurence Lundblade1341c592020-04-11 14:19:05 -07002506 goto Done;
2507 }
2508 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002509
Laurence Lundblade1341c592020-04-11 14:19:05 -07002510 if(puNextNestLevel != NULL) {
2511 *puNextNestLevel = Item.uNextNestLevel;
2512 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002513 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002514
Laurence Lundblade1341c592020-04-11 14:19:05 -07002515 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002517 if(puNextNestLevel != NULL) {
2518 /* Just pass the nesting level through */
2519 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2520 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002521 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002522 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002523
2524Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002525 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002526}
2527
2528
Laurence Lundblade1341c592020-04-11 14:19:05 -07002529/* Return true if the labels in Item1 and Item2 are the same.
2530 Works only for integer and string labels. Returns false
2531 for any other type. */
2532static inline bool
2533MatchLabel(QCBORItem Item1, QCBORItem Item2)
2534{
2535 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2536 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2537 return true;
2538 }
2539 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002540 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002541 return true;
2542 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002543 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002544 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2545 return true;
2546 }
2547 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2548 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2549 return true;
2550 }
2551 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002552
Laurence Lundblade1341c592020-04-11 14:19:05 -07002553 /* Other label types are never matched */
2554 return false;
2555}
2556
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002557
2558/*
2559 Returns true if Item1 and Item2 are the same type
2560 or if either are of QCBOR_TYPE_ANY.
2561 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002562static inline bool
2563MatchType(QCBORItem Item1, QCBORItem Item2)
2564{
2565 if(Item1.uDataType == Item2.uDataType) {
2566 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002567 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002568 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002569 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002570 return true;
2571 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002572 return false;
2573}
2574
2575
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002576/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002577 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002578
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002579 @param[in] pMe The decode context to search.
2580 @param[in,out] pItemArray The items to search for and the items found.
2581 @param[out] puOffset Byte offset of last item matched.
2582 @param[in] pCBContext Context for the not-found item call back.
2583 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002584
2585 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2586
Laurence Lundblade9b334962020-08-27 10:55:53 -07002587 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2588 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2589 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002590
2591 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2592
2593 @retval Also errors returned by QCBORDecode_GetNext().
2594
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002595 On input pItemArray contains a list of labels and data types
2596 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002597
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002598 On output the fully retrieved items are filled in with
2599 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002600
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002601 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002602 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002603static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002604MapSearch(QCBORDecodeContext *pMe,
2605 QCBORItem *pItemArray,
2606 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002607 void *pCBContext,
2608 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002609{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002610 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002611 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002612
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002613 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002614 uReturn = pMe->uLastError;
2615 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002616 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002617
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002618 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002619 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2620 /* QCBOR_TYPE_NONE as first item indicates just looking
2621 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002622 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2623 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002624 }
2625
Laurence Lundblade085d7952020-07-24 10:26:30 -07002626 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2627 // It is an empty bounded array or map
2628 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2629 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002630 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002631 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002632 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002633 // Nothing is ever found in an empty array or map. All items
2634 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002635 uReturn = QCBOR_SUCCESS;
2636 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002637 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002638 }
2639
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002640 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002641 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2642
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002643 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002644 UsefulInputBuf_Seek(&(pMe->InBuf),
2645 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002646
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002647 /*
2648 Loop over all the items in the map. They could be
2649 deeply nested and this should handle both definite
2650 and indefinite length maps and arrays, so this
2651 adds some complexity.
2652 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002653 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002654 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002655 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002656 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002657 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002658
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002659 /* Get the item */
2660 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002661 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002662 if(QCBORDecode_IsNotWellFormed(uReturn)) {
2663 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002664 // TODO: also bail out on implementation limits like array too big
Laurence Lundblade1341c592020-04-11 14:19:05 -07002665 goto Done;
2666 }
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002667 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2668 // Unexpected end of map or array.
2669 goto Done;
2670 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002671
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002672 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002673 bool bMatched = false;
2674 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002675 // TODO: have label filled in on invalid CBOR so error reporting
Laurence Lundblade9b334962020-08-27 10:55:53 -07002676 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002677 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002678 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002679 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2680 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002681 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002682 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002683 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002684 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002685 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002686 goto Done;
2687 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002688
Laurence Lundblade1341c592020-04-11 14:19:05 -07002689 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002690 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002691 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002692 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002693 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002694 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002695 bMatched = true;
2696 }
2697 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002698
2699
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002700 if(!bMatched && pfCallback != NULL) {
2701 /*
2702 Call the callback on unmatched labels.
2703 (It is tempting to do duplicate detection here, but that would
2704 require dynamic memory allocation because the number of labels
2705 that might be encountered is unbounded.)
2706 */
2707 uReturn = (*pfCallback)(pCBContext, &Item);
2708 if(uReturn != QCBOR_SUCCESS) {
2709 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002710 }
2711 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002712
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002713 /*
2714 Consume the item whether matched or not. This
2715 does the work of traversing maps and array and
2716 everything in them. In this loop only the
2717 items at the current nesting level are examined
2718 to match the labels.
2719 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002720 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002721 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002722 goto Done;
2723 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002724
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002725 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002726
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002727 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002728
2729 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002730 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2731 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002732
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002733 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002734 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2735
2736 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002737 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2738 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002739 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002740 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002741 }
2742 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002743
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002744 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002745}
2746
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002747
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002748/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002749 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002750*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002751void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2752 int64_t nLabel,
2753 uint8_t uQcborType,
2754 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002755{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002756 if(pMe->uLastError != QCBOR_SUCCESS) {
2757 return;
2758 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002760 QCBORItem OneItemSeach[2];
2761 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2762 OneItemSeach[0].label.int64 = nLabel;
2763 OneItemSeach[0].uDataType = uQcborType;
2764 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002765
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002766 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2767 if(uReturn != QCBOR_SUCCESS) {
2768 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002769 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002770 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002771 uReturn = QCBOR_ERR_NOT_FOUND;
2772 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002773 }
2774
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002775 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002776
2777 Done:
2778 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002779}
2780
2781
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002782/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002783 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002784*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002785void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2786 const char *szLabel,
2787 uint8_t uQcborType,
2788 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002789{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002790 if(pMe->uLastError != QCBOR_SUCCESS) {
2791 return;
2792 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002793
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002794 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002795 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2796 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2797 OneItemSeach[0].uDataType = uQcborType;
2798 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002799
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002800 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2801 if(uReturn != QCBOR_SUCCESS) {
2802 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002803 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002804 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002805 uReturn = QCBOR_ERR_NOT_FOUND;
2806 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002807 }
2808
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002809 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002810
2811Done:
2812 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002813}
2814
2815
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002816
Laurence Lundblade9b334962020-08-27 10:55:53 -07002817static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002818{
2819 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2820 if(uDataType == puTypeList[i]) {
2821 return QCBOR_SUCCESS;
2822 }
2823 }
2824 return QCBOR_ERR_UNEXPECTED_TYPE;
2825}
2826
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002827
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002828/**
2829 @param[in] TagSpec Specification for matching tags.
2830 @param[in] uDataType A QCBOR data type
Laurence Lundblade9b334962020-08-27 10:55:53 -07002831
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002832 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2833 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002834
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002835 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2836 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002837static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002838{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002839 if((TagSpec.uTagRequirement & (~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS)) == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002840 // Must match the tag and only the tag
2841 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002842 }
2843
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002844 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2845 if(uReturn == QCBOR_SUCCESS) {
2846 return QCBOR_SUCCESS;
2847 }
2848
Laurence Lundblade9b334962020-08-27 10:55:53 -07002849 if((TagSpec.uTagRequirement & (~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS)) == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002850 /* Must match the content type and only the content type.
2851 There was no match just above so it is a fail. */
2852 return QCBOR_ERR_UNEXPECTED_TYPE;
2853 }
2854
2855 /* If here it can match either the tag or the content
2856 and it hasn't matched the content, so the end
2857 result is whether it matches the tag. This is
2858 also the case that the CBOR standard discourages. */
2859
2860 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002861}
2862
Laurence Lundblade9b334962020-08-27 10:55:53 -07002863static QCBORError CheckTagRequirement2(const TagSpecification TagSpec, const QCBORItem *pItem)
2864{
2865 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2866 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2867 /* There are tags that QCBOR couldn't process on this item and
2868 the caller has told us there should not be. */
2869 return QCBOR_ERR_UNEXPECTED_TYPE;
2870 }
2871
2872 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2873 const int nItemType = pItem->uDataType;
2874
2875 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2876 // Must match the tag and only the tag
2877 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2878 }
2879
2880 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2881 if(uReturn == QCBOR_SUCCESS) {
2882 return QCBOR_SUCCESS;
2883 }
2884
2885 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2886 /* Must match the content type and only the content type.
2887 There was no match just above so it is a fail. */
2888 return QCBOR_ERR_UNEXPECTED_TYPE;
2889 }
2890
2891 /* If here it can match either the tag or the content
2892 and it hasn't matched the content, so the end
2893 result is whether it matches the tag. This is
2894 also the case that the CBOR standard discourages. */
2895
2896 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2897}
2898
2899#if 0
2900/**
2901 @param[in] TagSpec Specification for matching tags.
2902 @param[in] uDataType A QCBOR data type
2903
2904 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2905 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2906
2907 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2908 */
2909static QCBORError CheckTagRequirement2(const TagSpecification TagSpec, uint8_t uDataType)
2910{
2911 const uint16_t *pTags;
2912/*
2913For all the tag-specific accessor methods supported, GetNext will
2914 process then automatically when encountered during decoding.
2915 The will have a QCBOR_TYPE and a representation in QCBORItem.
2916 There are no expections to this (so far).
2917
2918 That means the tag list in the QCBORItem will never have
2919 these tags in it. The tags in that list never need to
2920 be examined here.
2921
2922
2923
29241 Tag list must be empty
2925
29262 and 5, first tag must be in expected list
2927
29284
2929
29303 tag list must be empty or one in the expected list
2931
29326, if first tag is expected, consume it, pass the rest on
2933
2934
2935 */
2936
2937 /*
2938 First thing to understand is that GetNext will have processed
2939 the tags this code knows about. They will not be in the unprocessed
2940 tags list and the dataType will be of the processed CBOR.
2941 */
2942
2943 const bool bUnprocessedTagsEmpty = pTags[0] != CBOR_TAG_INVALID16;
2944
2945 const bool bDataTypeMatchesRequestedTaggedType = !CheckTypeList(uDataType, TagSpec.uTaggedTypes);
2946
2947 const bool bDataTypeMatchesRequestedContentType = !CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2948
2949
2950 if(TagSpec.uTagRequirement == 1) {
2951 /* There should be no tags at all, so the unprocessed tag
2952 list should be empty.
2953
2954 The content has to match the expected content. If
2955 there was a tag that was interpreted, the content
2956 wouldn't match.
2957
2958 */
2959 if(!bUnprocessedTagsEmpty) {
2960 return QCBOR_ERR_UNEXPECTED_TYPE;
2961 } else {
2962 if(!bDataTypeMatchesRequestedContentType) {
2963 return QCBOR_ERR_UNEXPECTED_TYPE;
2964 } else {
2965 return QCBOR_SUCCESS;
2966 }
2967
2968 }
2969
2970
2971
2972 } else if(TagSpec.uTagRequirement == 2) {
2973 /* The tag was present so GetNext will have interpreted it by now.
2974 The data type should be one of the requested types
2975 and there should be no other tags. */
2976
2977 if(!bUnprocessedTagsEmpty) {
2978 return QCBOR_ERR_UNEXPECTED_TYPE;
2979 } else {
2980 if(!bDataTypeMatchesRequestedTaggedType) {
2981 return QCBOR_ERR_UNEXPECTED_TYPE;
2982 } else {
2983 return QCBOR_SUCCESS;
2984 }
2985 }
2986 } else if(TagSpec.uTagRequirement == 3) {
2987 if(!bUnprocessedTagsEmpty) {
2988 return QCBOR_ERR_UNEXPECTED_TYPE;
2989 } else {
2990 if(bDataTypeMatchesRequestedTaggedType || bDataTypeMatchesRequestedContentType) {
2991 return true;
2992 } else {
2993 return false;
2994 }
2995 }
2996 } else if(TagSpec.uTagRequirement == 4) {
2997
2998
2999
3000
3001
3002
3003
3004 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_TAG) {
3005 // Must match the tag and only the tag
3006 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
3007 }
3008
3009 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
3010 if(uReturn == QCBOR_SUCCESS) {
3011 return QCBOR_SUCCESS;
3012 }
3013
3014 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3015 /* Must match the content type and only the content type.
3016 There was no match just above so it is a fail. */
3017 return QCBOR_ERR_UNEXPECTED_TYPE;
3018 }
3019
3020 /* If here it can match either the tag or the content
3021 and it hasn't matched the content, so the end
3022 result is whether it matches the tag. This is
3023 also the case that the CBOR standard discourages. */
3024
3025 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
3026}
3027
3028#endif
3029
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003030
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003031// Semi-private
3032// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003033void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3034 int64_t nLabel,
3035 TagSpecification TagSpec,
3036 QCBORItem *pItem)
3037{
3038 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3039 if(pMe->uLastError != QCBOR_SUCCESS) {
3040 return;
3041 }
3042
Laurence Lundblade9b334962020-08-27 10:55:53 -07003043 pMe->uLastError = (uint8_t)CheckTagRequirement2(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003044}
3045
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003046// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003047void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3048 const char *szLabel,
3049 TagSpecification TagSpec,
3050 QCBORItem *pItem)
3051{
3052 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3053 if(pMe->uLastError != QCBOR_SUCCESS) {
3054 return;
3055 }
3056
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003057 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003058}
3059
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003060// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003061void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3062 int64_t nLabel,
3063 TagSpecification TagSpec,
3064 UsefulBufC *pString)
3065{
3066 QCBORItem Item;
3067 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3068 if(pMe->uLastError == QCBOR_SUCCESS) {
3069 *pString = Item.val.string;
3070 }
3071}
3072
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003073// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003074void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3075 const char * szLabel,
3076 TagSpecification TagSpec,
3077 UsefulBufC *pString)
3078{
3079 QCBORItem Item;
3080 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3081 if(pMe->uLastError == QCBOR_SUCCESS) {
3082 *pString = Item.val.string;
3083 }
3084}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003085
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003086/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003087 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003088*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003089QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
3090{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003091 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003092}
3093
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003094/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003095 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003096*/
3097QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
3098 QCBORItem *pItemList,
3099 void *pCallbackCtx,
3100 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003101{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003102 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003103}
3104
3105
Laurence Lundblade34691b92020-05-18 22:25:25 -07003106static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003107{
Laurence Lundblade085d7952020-07-24 10:26:30 -07003108 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07003109 if(pMe->uLastError != QCBOR_SUCCESS) {
3110 // Already in error state; do nothing.
3111 return;
3112 }
3113
3114 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003115 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003116 if(pMe->uLastError != QCBOR_SUCCESS) {
3117 return;
3118 }
3119
Laurence Lundblade9b334962020-08-27 10:55:53 -07003120 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
3121 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
3122 return;
3123 }
3124
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003125 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07003126 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003127
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003128 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003129 be at the right place.
3130
3131 The UsefulInBuf offset could be anywhere, so no assumption is
3132 made about it.
3133
3134 No assumption is made about the pre-order nesting level either.
3135
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003136 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003137 the map level that is being entered.
3138 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003139 /* Seek to the data item that is the map or array */
3140 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003141
3142 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003143
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003144 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003145}
3146
3147
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003148/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003149 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003150*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003151void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003152{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003153 QCBORItem OneItemSeach[2];
3154 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3155 OneItemSeach[0].label.int64 = nLabel;
3156 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3157 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003158
Laurence Lundblade9b334962020-08-27 10:55:53 -07003159 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003160 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003161}
3162
3163
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003164/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003165 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003166*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003167void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003168{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003169 QCBORItem OneItemSeach[2];
3170 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3171 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3172 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3173 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003174
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003175 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003176}
3177
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003178/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003179 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003180*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003181void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003182{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003183 QCBORItem OneItemSeach[2];
3184 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3185 OneItemSeach[0].label.int64 = nLabel;
3186 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3187 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003188
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003189 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003190}
3191
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003192/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003193 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003194*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003195void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3196{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003197 QCBORItem OneItemSeach[2];
3198 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3199 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3200 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3201 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003202
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003203 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003204}
3205
3206
Laurence Lundblade02625d42020-06-25 14:41:41 -07003207// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003208void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003209{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003210 QCBORError uErr;
3211
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003212 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003213 if(pMe->uLastError != QCBOR_SUCCESS) {
3214 // Already in error state; do nothing.
3215 return;
3216 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003217
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003218 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003219 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003220 uErr = QCBORDecode_GetNext(pMe, &Item);
3221 if(uErr != QCBOR_SUCCESS) {
3222 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003223 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003224 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003225 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3226 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003227 }
3228
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003229 CopyTags(pMe, &Item);
3230
3231
Laurence Lundbladef0499502020-08-01 11:55:57 -07003232 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003233 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003234 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3235 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003236 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003237 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3238 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003239 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3240 DecodeNesting_Descend(&(pMe->nesting), uType);
3241 }
3242
Laurence Lundblade02625d42020-06-25 14:41:41 -07003243 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003244
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003245 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3246 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003247
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003248Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003249 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003250}
3251
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252
3253/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003254 This is the common work for exiting a level that is a bounded map, array or bstr
3255 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003256
3257 One chunk of work is to set up the pre-order traversal so it is at
3258 the item just after the bounded map, array or bstr that is being
3259 exited. This is somewhat complex.
3260
3261 The other work is to level-up the bounded mode to next higest bounded
3262 mode or the top level if there isn't one.
3263 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003264static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003265ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003266{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003267 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003268
Laurence Lundblade02625d42020-06-25 14:41:41 -07003269 /*
3270 First the pre-order-traversal byte offset is positioned to the
3271 item just after the bounded mode item that was just consumed.
3272 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003273 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3274
Laurence Lundblade02625d42020-06-25 14:41:41 -07003275 /*
3276 Next, set the current nesting level to one above the bounded level
3277 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003278
Laurence Lundblade02625d42020-06-25 14:41:41 -07003279 DecodeNesting_CheckBoundedType() is always called before this and
3280 makes sure pCurrentBounded is valid.
3281 */
3282 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3283
3284 /*
3285 This does the complex work of leveling up the pre-order traversal
3286 when the end of a map or array or another bounded level is
3287 reached. It may do nothing, or ascend all the way to the top
3288 level.
3289 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003290 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003291 if(uErr != QCBOR_SUCCESS) {
3292 goto Done;
3293 }
3294
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295 /*
3296 This makes the next highest bounded level the current bounded
3297 level. If there is no next highest level, then no bounded mode is
3298 in effect.
3299 */
3300 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003301
Laurence Lundblade02625d42020-06-25 14:41:41 -07003302 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003303
3304Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003305 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003306 return uErr;
3307}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003308
Laurence Lundblade02625d42020-06-25 14:41:41 -07003309
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003310// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003311void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003312{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003313 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003314 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003315 return;
3316 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003317
Laurence Lundblade02625d42020-06-25 14:41:41 -07003318 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003319
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003320 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003321 uErr = QCBOR_ERR_CLOSE_MISMATCH;
3322 goto Done;
3323 }
3324
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325 /*
3326 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003327 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003328 from previous map search, then do a dummy search.
3329 */
3330 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003331 QCBORItem Dummy;
3332 Dummy.uLabelType = QCBOR_TYPE_NONE;
3333 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3334 if(uErr != QCBOR_SUCCESS) {
3335 goto Done;
3336 }
3337 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003338
Laurence Lundblade02625d42020-06-25 14:41:41 -07003339 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003340
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003341Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003342 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003343}
3344
3345
Laurence Lundblade1341c592020-04-11 14:19:05 -07003346
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003347static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003348 const QCBORItem *pItem,
3349 uint8_t uTagRequirement,
3350 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003351{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003352 if(pBstr) {
3353 *pBstr = NULLUsefulBufC;
3354 }
3355
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003356 if(pMe->uLastError != QCBOR_SUCCESS) {
3357 // Already in error state; do nothing.
3358 return pMe->uLastError;
3359 }
3360
3361 QCBORError uError = QCBOR_SUCCESS;
3362
3363 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3364 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3365 goto Done;;
3366 }
3367
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003368 const TagSpecification TagSpec =
3369 {
3370 uTagRequirement,
3371 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3372 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3373 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003374
3375 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
3376 if(uError != QCBOR_SUCCESS) {
3377 goto Done;
3378 }
3379
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003380 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003381 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003382 so the increment in NestLevelAscender called by ExitBoundedLevel()
3383 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003384 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003385 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003386
3387 if(pBstr) {
3388 *pBstr = pItem->val.string;
3389 }
3390
3391 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003392
3393 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003394 // Most of these calls are simple inline accessors so this doesn't
3395 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003396 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003397 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3398 // TODO: test this error condition
3399 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
3400 goto Done;
3401 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003402 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003403 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003404
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003405 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003407 (uint32_t)uPreviousLength,
3408 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003409Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003410 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003411
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003412 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003413}
3414
3415
Laurence Lundblade02625d42020-06-25 14:41:41 -07003416/*
3417 Public function, see header qcbor/qcbor_decode.h file
3418 */
3419void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003420 uint8_t uTagRequirement,
3421 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003422{
3423 if(pMe->uLastError != QCBOR_SUCCESS) {
3424 // Already in error state; do nothing.
3425 return;
3426 }
3427
3428 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003429 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003430 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3431 if(pMe->uLastError != QCBOR_SUCCESS) {
3432 return;
3433 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003434
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003435 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003436 &Item,
3437 uTagRequirement,
3438 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003439}
3440
3441
Laurence Lundblade02625d42020-06-25 14:41:41 -07003442/*
3443 Public function, see header qcbor/qcbor_decode.h file
3444 */
3445void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003446 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003447 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003448 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003449{
3450 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003451 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003452
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003453 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003454}
3455
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003456
Laurence Lundblade02625d42020-06-25 14:41:41 -07003457/*
3458 Public function, see header qcbor/qcbor_decode.h file
3459 */
3460void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003461 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003462 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003463 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003464{
3465 QCBORItem Item;
3466 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3467
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003468 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003469}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003470
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003471
Laurence Lundblade02625d42020-06-25 14:41:41 -07003472/*
3473 Public function, see header qcbor/qcbor_decode.h file
3474 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003475void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003476{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003477 if(pMe->uLastError != QCBOR_SUCCESS) {
3478 // Already in error state; do nothing.
3479 return;
3480 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003481
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003482 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003483 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3484 return;
3485 }
3486
3487 /*
3488 Reset the length of the UsefulInputBuf to what it was before
3489 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003490 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003491 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3492 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003493
3494
Laurence Lundblade02625d42020-06-25 14:41:41 -07003495 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003496 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003497}
3498
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003499
Laurence Lundbladee6430642020-03-14 21:15:44 -07003500
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003501
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003502
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003503
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003504
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003505
Laurence Lundblade9b334962020-08-27 10:55:53 -07003506static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003507{
3508 switch(pItem->uDataType) {
3509 case QCBOR_TYPE_TRUE:
3510 *pBool = true;
3511 return QCBOR_SUCCESS;
3512 break;
3513
3514 case QCBOR_TYPE_FALSE:
3515 *pBool = false;
3516 return QCBOR_SUCCESS;
3517 break;
3518
3519 default:
3520 return QCBOR_ERR_UNEXPECTED_TYPE;
3521 break;
3522 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003523 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003524}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003525
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003526
Laurence Lundblade9b334962020-08-27 10:55:53 -07003527
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003528/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003529 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003530*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003531void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003532{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003533 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003534 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003535 return;
3536 }
3537
Laurence Lundbladec4537442020-04-14 18:53:22 -07003538 QCBORError nError;
3539 QCBORItem Item;
3540
3541 nError = QCBORDecode_GetNext(pMe, &Item);
3542 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003543 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003544 return;
3545 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003546 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003547}
3548
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003549
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003550/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003551 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003552*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003553void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003554{
3555 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003556 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003557
Laurence Lundblade9b334962020-08-27 10:55:53 -07003558 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003559}
3560
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003561
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003562/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003563 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003564*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003565void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3566{
3567 QCBORItem Item;
3568 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3569
Laurence Lundblade9b334962020-08-27 10:55:53 -07003570 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003571}
3572
3573
3574
Laurence Lundblade9b334962020-08-27 10:55:53 -07003575/*
3576 A number of methods decode CBOR that is associated with a
3577 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003578
Laurence Lundblade9b334962020-08-27 10:55:53 -07003579 The API of the method returns the
3580 data in a way specific to the
3581
3582 No tags at all.
3583
3584
3585 Require tag for the particular type for the method and no other.
3586
3587
3588 Either no tags at all or the particular type for the method and no other.
3589
3590 No tag for particular type; pass other tags along.
3591
3592 Require the tag for the particular type; pass other tags along
3593
3594 Any tagging is OK; consume the tag for the particular type if present,
3595 pass other tags along.
3596
3597
3598 1) REQUIRED
3599- 1 XXXX -- works
3600- T 1 XXX -- works, T is returned
3601
3602 if(tag is of interest) {
3603 process content
3604 return T if present
3605 }
3606
3607
3608 2) FORBIDDEN
3609 - XXX -- works
3610 - T XXX -- ???
3611
3612 if(tag is of interest) {
3613 error out since tag is forbidden
3614 } else {
3615 process contents
3616 return T
3617 }
3618
3619 3) OPTIONAL
3620 - XXX works
3621 - 1 XXX works
3622 - T XXX
3623 - T 1 XXX works, T is returned
3624
3625if (inner tag is of interest) {
3626 process content
3627 return tag T if present
3628 } else if (there is no tag) {
3629 process content
3630 } else {
3631 process content if possible
3632 return T
3633 }
3634
3635A field is type X
3636 - tag for type X is REQUIRED
3637 - tag for type X is FORBIDDEN
3638 - tag for type X is optional
3639 - Other tags are FORBIDDEN
3640 - Other tags are ALLOWED
3641
3642
3643
3644 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003645
3646static void ProcessEpochDate(QCBORDecodeContext *pMe,
3647 QCBORItem *pItem,
3648 uint8_t uTagRequirement,
3649 int64_t *pnTime)
3650{
3651 if(pMe->uLastError != QCBOR_SUCCESS) {
3652 // Already in error state, do nothing
3653 return;
3654 }
3655
3656 QCBORError uErr;
3657
3658 const TagSpecification TagSpec =
3659 {
3660 uTagRequirement,
3661 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3662 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3663 };
3664
Laurence Lundblade4b270642020-08-14 12:53:07 -07003665 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003666 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3667 // only has three target types.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003668 uErr = CheckTagRequirement2(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003669 if(uErr != QCBOR_SUCCESS) {
3670 goto Done;
3671 }
3672
3673 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3674 uErr = DecodeDateEpoch(pItem);
3675 if(uErr != QCBOR_SUCCESS) {
3676 goto Done;
3677 }
3678 }
3679
Laurence Lundblade9b334962020-08-27 10:55:53 -07003680 // Save the tags in the last item's tags in the decode context
3681 // for QCBORDecode_GetNthTagOfLast()
3682 CopyTags(pMe, pItem);
3683
Laurence Lundbladec7114722020-08-13 05:11:40 -07003684 *pnTime = pItem->val.epochDate.nSeconds;
3685
3686Done:
3687 pMe->uLastError = (uint8_t)uErr;
3688}
3689
3690
3691void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3692 uint8_t uTagRequirement,
3693 int64_t *pnTime)
3694{
3695 if(pMe->uLastError != QCBOR_SUCCESS) {
3696 // Already in error state, do nothing
3697 return;
3698 }
3699
3700 QCBORItem Item;
3701 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3702
3703 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3704}
3705
3706
3707void
3708QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3709 int64_t nLabel,
3710 uint8_t uTagRequirement,
3711 int64_t *pnTime)
3712{
3713 QCBORItem Item;
3714 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3715 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3716}
3717
3718
3719void
3720QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3721 const char *szLabel,
3722 uint8_t uTagRequirement,
3723 int64_t *pnTime)
3724{
3725 QCBORItem Item;
3726 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3727 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3728}
3729
3730
3731
3732
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003733void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3734 TagSpecification TagSpec,
3735 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003736{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003737 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003738 // Already in error state, do nothing
3739 return;
3740 }
3741
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003742 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003743 QCBORItem Item;
3744
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003745 uError = QCBORDecode_GetNext(pMe, &Item);
3746 if(uError != QCBOR_SUCCESS) {
3747 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003748 return;
3749 }
3750
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003751 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3752
3753 if(pMe->uLastError == QCBOR_SUCCESS) {
3754 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003755 } else {
3756 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003757 }
3758}
3759
Laurence Lundbladec4537442020-04-14 18:53:22 -07003760
3761
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003762
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003763static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003764 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003765 UsefulBufC *pValue,
3766 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003767{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003768 const TagSpecification TagSpec =
3769 {
3770 uTagRequirement,
3771 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3772 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3773 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003774
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003775 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3776 if(uErr != QCBOR_SUCCESS) {
3777 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003778 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003779
3780 *pValue = pItem->val.string;
3781
3782 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3783 *pbIsNegative = false;
3784 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3785 *pbIsNegative = true;
3786 }
3787
3788 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003789}
3790
3791
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003792/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003793 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003794 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003795void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3796 uint8_t uTagRequirement,
3797 UsefulBufC *pValue,
3798 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003799{
3800 if(pMe->uLastError != QCBOR_SUCCESS) {
3801 // Already in error state, do nothing
3802 return;
3803 }
3804
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003805 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003806 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3807 if(uError != QCBOR_SUCCESS) {
3808 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003809 return;
3810 }
3811
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003812 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003813}
3814
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003815
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003816/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003817 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003818*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003819void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3820 int64_t nLabel,
3821 uint8_t uTagRequirement,
3822 UsefulBufC *pValue,
3823 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003824{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003825 QCBORItem Item;
3826 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003827 if(pMe->uLastError != QCBOR_SUCCESS) {
3828 return;
3829 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003830
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003831 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003832}
3833
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003834
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003835/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003836 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003837*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003838void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3839 const char *szLabel,
3840 uint8_t uTagRequirement,
3841 UsefulBufC *pValue,
3842 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003843{
3844 QCBORItem Item;
3845 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003846 if(pMe->uLastError != QCBOR_SUCCESS) {
3847 return;
3848 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003849
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003850 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003851}
3852
3853
3854
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003855
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003856// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003857QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3858 const QCBORItem *pItem,
3859 UsefulBufC *pMessage,
3860 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003861{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003862 const TagSpecification TagSpecText =
3863 {
3864 uTagRequirement,
3865 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3866 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3867 };
3868 const TagSpecification TagSpecBinary =
3869 {
3870 uTagRequirement,
3871 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3872 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3873 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003874
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003875 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003876
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003877 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003878 *pMessage = pItem->val.string;
3879 if(pbIsNot7Bit != NULL) {
3880 *pbIsNot7Bit = false;
3881 }
3882 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003883 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003884 *pMessage = pItem->val.string;
3885 if(pbIsNot7Bit != NULL) {
3886 *pbIsNot7Bit = true;
3887 }
3888 uReturn = QCBOR_SUCCESS;
3889
3890 } else {
3891 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3892 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003893
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003894 return uReturn;
3895}
3896
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003897// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3898
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003899
3900
3901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003902#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003903
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003904typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003905
3906
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003907// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003908static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003909{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003910 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003911
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003912 if(uResult != 0) {
3913 /* This loop will run a maximum of 19 times because
3914 * UINT64_MAX < 10 ^^ 19. More than that will cause
3915 * exit with the overflow error
3916 */
3917 for(; nExponent > 0; nExponent--) {
3918 if(uResult > UINT64_MAX / 10) {
3919 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3920 }
3921 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003922 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003923
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003924 for(; nExponent < 0; nExponent++) {
3925 uResult = uResult / 10;
3926 if(uResult == 0) {
3927 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3928 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003929 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003930 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003931 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003932
3933 *puResult = uResult;
3934
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003935 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003936}
3937
3938
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003939// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003940static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003941{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003942 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003943
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003944 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003945
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003946 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003947 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003948 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003949 */
3950 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003951 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003952 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003953 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003954 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003955 nExponent--;
3956 }
3957
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003958 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003959 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003960 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3961 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003962 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003963 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003964 }
3965
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003966 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003967
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003968 return QCBOR_SUCCESS;
3969}
3970
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003971
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003972/*
3973 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3974 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003975static inline QCBORError ExponentiateNN(int64_t nMantissa,
3976 int64_t nExponent,
3977 int64_t *pnResult,
3978 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003979{
3980 uint64_t uResult;
3981
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003982 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003983 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003984 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3985
3986 // Do the exponentiation of the positive mantissa
3987 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3988 if(uReturn) {
3989 return uReturn;
3990 }
3991
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003992
Laurence Lundblade983500d2020-05-14 11:49:34 -07003993 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3994 of INT64_MIN. This assumes two's compliment representation where
3995 INT64_MIN is one increment farther from 0 than INT64_MAX.
3996 Trying to write -INT64_MIN doesn't work to get this because the
3997 compiler tries to work with an int64_t which can't represent
3998 -INT64_MIN.
3999 */
4000 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4001
4002 // Error out if too large
4003 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004004 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4005 }
4006
4007 // Casts are safe because of checks above
4008 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4009
4010 return QCBOR_SUCCESS;
4011}
4012
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004013
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004014/*
4015 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
4016 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004017static inline QCBORError ExponentitateNU(int64_t nMantissa,
4018 int64_t nExponent,
4019 uint64_t *puResult,
4020 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004021{
4022 if(nMantissa < 0) {
4023 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4024 }
4025
4026 // Cast to unsigned is OK because of check for negative
4027 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4028 // Exponentiation is straight forward
4029 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4030}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004031
4032
4033/*
4034 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
4035 */
4036static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4037 int64_t nExponent,
4038 uint64_t *puResult,
4039 fExponentiator pfExp)
4040{
4041 return (*pfExp)(uMantissa, nExponent, puResult);
4042}
4043
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004044#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4045
4046
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004047
4048
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004049
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004050static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004051{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004052 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004053
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004054 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004055 const uint8_t *pByte = BigNum.ptr;
4056 size_t uLen = BigNum.len;
4057 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004058 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004059 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004060 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004061 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004062 }
4063
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004064 *pResult = uResult;
4065 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004066}
4067
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004068
Laurence Lundblade887add82020-05-17 05:50:34 -07004069static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004071 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004072}
4073
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004074
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004075static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004076{
4077 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004078 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4079 if(uError) {
4080 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004081 }
4082 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4083 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004084 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004085}
4086
4087
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004088static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004089{
4090 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004091 /* The negative integer furthest from zero for a C int64_t is
4092 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4093 negative number in CBOR is computed as -n - 1 where n is the
4094 encoded integer, where n is what is in the variable BigNum. When
4095 converting BigNum to a uint64_t, the maximum value is thus
4096 INT64_MAX, so that when it -n - 1 is applied to it the result will
4097 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004098
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004099 -n - 1 <= INT64_MIN.
4100 -n - 1 <= -INT64_MAX - 1
4101 n <= INT64_MAX.
4102 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004103 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004104 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004105 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004106 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004107
4108 /// Now apply -n - 1. The cast is safe because
4109 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4110 // is the largest positive integer that an int64_t can
4111 // represent. */
4112 *pnResult = -(int64_t)uResult - 1;
4113
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004114 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004115}
4116
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004117
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004118
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004119
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004120#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07004121
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004122
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004123/*
4124Convert a integers and floats to an int64_t.
4125
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004126\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004127
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004128\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004129
4130\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4131
4132\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4133
4134*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004135static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136{
4137 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004138 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004139 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004140#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004142 // TODO: what about under/overflow here?
4143 // Invokes the floating-point HW and/or compiler-added libraries
4144 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004145 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4146 *pnValue = llround(pItem->val.dfnum);
4147 } else {
4148 *pnValue = lroundf(pItem->val.fnum);
4149 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 if(fetestexcept(FE_INVALID)) {
4151 // TODO: better error code
4152 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4153 }
4154 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004156 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004157#else
4158 return QCBOR_ERR_HW_FLOAT_DISABLED;
4159#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160 break;
4161
4162 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004163 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004164 *pnValue = pItem->val.int64;
4165 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 }
4168 break;
4169
4170 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004172 if(pItem->val.uint64 < INT64_MAX) {
4173 *pnValue = pItem->val.int64;
4174 } else {
4175 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4176 }
4177 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004178 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004179 }
4180 break;
4181
4182 default:
4183 return QCBOR_ERR_UNEXPECTED_TYPE;
4184 }
4185 return QCBOR_SUCCESS;
4186}
4187
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004188
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004189void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004190 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004191 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004192 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004193{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004194 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004195 return;
4196 }
4197
Laurence Lundbladee6430642020-03-14 21:15:44 -07004198 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004199 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4200 if(uError) {
4201 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004202 return;
4203 }
4204
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004205 if(pItem) {
4206 *pItem = Item;
4207 }
4208
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004209 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004210}
4211
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004212
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4214 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004216 int64_t *pnValue,
4217 QCBORItem *pItem)
4218{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004219 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004220 if(pMe->uLastError != QCBOR_SUCCESS) {
4221 return;
4222 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004223
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004224 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225}
4226
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004227
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004228void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4229 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004230 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004231 int64_t *pnValue,
4232 QCBORItem *pItem)
4233{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004234 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004235 if(pMe->uLastError != QCBOR_SUCCESS) {
4236 return;
4237 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004238
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004239 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240}
4241
4242
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004243/*
4244 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004245
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004246 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004247
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004248 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004249
4250 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4251
4252 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4253
4254 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004255static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004256{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257 switch(pItem->uDataType) {
4258
4259 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004260 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004262 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004263 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004264 }
4265 break;
4266
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004267 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004268 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004269 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004270 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004271 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004272 }
4273 break;
4274
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004275#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4276 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004277 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004278 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004279 pItem->val.expAndMantissa.nExponent,
4280 pnValue,
4281 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004282 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004283 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004284 }
4285 break;
4286
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004287 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004288 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004289 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004290 pItem->val.expAndMantissa.nExponent,
4291 pnValue,
4292 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004293 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004294 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004295 }
4296 break;
4297
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004299 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004300 int64_t nMantissa;
4301 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004302 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4303 if(uErr) {
4304 return uErr;
4305 }
4306 return ExponentiateNN(nMantissa,
4307 pItem->val.expAndMantissa.nExponent,
4308 pnValue,
4309 Exponentitate10);
4310 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004311 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004312 }
4313 break;
4314
4315 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004316 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004317 int64_t nMantissa;
4318 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004319 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4320 if(uErr) {
4321 return uErr;
4322 }
4323 return ExponentiateNN(nMantissa,
4324 pItem->val.expAndMantissa.nExponent,
4325 pnValue,
4326 Exponentitate10);
4327 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004328 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004329 }
4330 break;
4331
4332 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004333 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004334 int64_t nMantissa;
4335 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004336 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4337 if(uErr) {
4338 return uErr;
4339 }
4340 return ExponentiateNN(nMantissa,
4341 pItem->val.expAndMantissa.nExponent,
4342 pnValue,
4343 Exponentitate2);
4344 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004345 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004346 }
4347 break;
4348
4349 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004350 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004351 int64_t nMantissa;
4352 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004353 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4354 if(uErr) {
4355 return uErr;
4356 }
4357 return ExponentiateNN(nMantissa,
4358 pItem->val.expAndMantissa.nExponent,
4359 pnValue,
4360 Exponentitate2);
4361 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004362 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004363 }
4364 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004365#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4366
Laurence Lundbladee6430642020-03-14 21:15:44 -07004367
Laurence Lundbladec4537442020-04-14 18:53:22 -07004368 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004369 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004370}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004371
4372
Laurence Lundbladec4537442020-04-14 18:53:22 -07004373/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004374 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004375 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004376void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004377{
4378 QCBORItem Item;
4379
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004380 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004381
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004382 if(pMe->uLastError == QCBOR_SUCCESS) {
4383 // The above conversion succeeded
4384 return;
4385 }
4386
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004387 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004388 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004389 return;
4390 }
4391
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004392 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004393}
4394
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395
4396/*
4397Public function, see header qcbor/qcbor_decode.h file
4398*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004399void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4400 int64_t nLabel,
4401 uint32_t uConvertTypes,
4402 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004403{
4404 QCBORItem Item;
4405
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004407
4408 if(pMe->uLastError == QCBOR_SUCCESS) {
4409 // The above conversion succeeded
4410 return;
4411 }
4412
4413 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4414 // The above conversion failed in a way that code below can't correct
4415 return;
4416 }
4417
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004418 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004419}
4420
4421
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422/*
4423Public function, see header qcbor/qcbor_decode.h file
4424*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004425void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4426 const char *szLabel,
4427 uint32_t uConvertTypes,
4428 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004429{
4430 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004431 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004432
4433 if(pMe->uLastError == QCBOR_SUCCESS) {
4434 // The above conversion succeeded
4435 return;
4436 }
4437
4438 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4439 // The above conversion failed in a way that code below can't correct
4440 return;
4441 }
4442
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004443 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004444}
4445
4446
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004447static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004448{
4449 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004450 case QCBOR_TYPE_DOUBLE:
4451 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004452#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004453 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4454 // TODO: this code needs work
4455 feclearexcept(FE_ALL_EXCEPT);
4456 double dRounded = round(pItem->val.dfnum);
4457 // TODO: over/underflow
4458 if(fetestexcept(FE_INVALID)) {
4459 // TODO: better error code
4460 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4461 } else if(isnan(dRounded)) {
4462 // TODO: better error code
4463 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4464 } else if(dRounded >= 0) {
4465 *puValue = (uint64_t)dRounded;
4466 } else {
4467 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4468 }
4469 } else {
4470 return QCBOR_ERR_UNEXPECTED_TYPE;
4471 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004472#else
4473 return QCBOR_ERR_HW_FLOAT_DISABLED;
4474#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004475 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004476
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004477 case QCBOR_TYPE_INT64:
4478 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4479 if(pItem->val.int64 >= 0) {
4480 *puValue = (uint64_t)pItem->val.int64;
4481 } else {
4482 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4483 }
4484 } else {
4485 return QCBOR_ERR_UNEXPECTED_TYPE;
4486 }
4487 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004489 case QCBOR_TYPE_UINT64:
4490 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4491 *puValue = pItem->val.uint64;
4492 } else {
4493 return QCBOR_ERR_UNEXPECTED_TYPE;
4494 }
4495 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004496
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004497 default:
4498 return QCBOR_ERR_UNEXPECTED_TYPE;
4499 }
4500
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 return QCBOR_SUCCESS;
4502}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004503
4504
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004505void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004506 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004508 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004509{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004510 if(pMe->uLastError != QCBOR_SUCCESS) {
4511 return;
4512 }
4513
Laurence Lundbladec4537442020-04-14 18:53:22 -07004514 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004515
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004516 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4517 if(uError) {
4518 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004519 return;
4520 }
4521
Laurence Lundbladea826c502020-05-10 21:07:00 -07004522 if(pItem) {
4523 *pItem = Item;
4524 }
4525
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004526 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004527}
4528
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004529
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004530void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004532 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004533 uint64_t *puValue,
4534 QCBORItem *pItem)
4535{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004536 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004537 if(pMe->uLastError != QCBOR_SUCCESS) {
4538 return;
4539 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004540
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004541 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004542}
4543
4544
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004545void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004547 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548 uint64_t *puValue,
4549 QCBORItem *pItem)
4550{
4551 if(pMe->uLastError != QCBOR_SUCCESS) {
4552 return;
4553 }
4554
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004555 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004556 if(pMe->uLastError != QCBOR_SUCCESS) {
4557 return;
4558 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004560 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561}
4562
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004563
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004564/*
4565 Public function, see header qcbor/qcbor_decode.h file
4566*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004567static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004569 switch(pItem->uDataType) {
4570
4571 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004572 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004573 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4574 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004575 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576 }
4577 break;
4578
4579 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004580 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4582 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004583 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584 }
4585 break;
4586
4587#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4588
4589 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004591 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004592 pItem->val.expAndMantissa.nExponent,
4593 puValue,
4594 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004597 }
4598 break;
4599
4600 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4603 pItem->val.expAndMantissa.nExponent,
4604 puValue,
4605 Exponentitate2);
4606 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608 }
4609 break;
4610
4611 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004612 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004613 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004614 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004615 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616 if(uErr != QCBOR_SUCCESS) {
4617 return uErr;
4618 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004619 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620 pItem->val.expAndMantissa.nExponent,
4621 puValue,
4622 Exponentitate10);
4623 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004624 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625 }
4626 break;
4627
4628 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004629 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004630 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4631 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004632 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633 }
4634 break;
4635
4636 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004637 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004638 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004639 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004640 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004641 if(uErr != QCBOR_SUCCESS) {
4642 return uErr;
4643 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004644 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645 pItem->val.expAndMantissa.nExponent,
4646 puValue,
4647 Exponentitate2);
4648 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004649 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004650 }
4651 break;
4652
4653 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004654 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004655 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4656 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004657 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004658 }
4659 break;
4660#endif
4661 default:
4662 return QCBOR_ERR_UNEXPECTED_TYPE;
4663 }
4664}
4665
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004666
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004667/*
4668 Public function, see header qcbor/qcbor_decode.h file
4669*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004671{
4672 QCBORItem Item;
4673
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004675
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004676 if(pMe->uLastError == QCBOR_SUCCESS) {
4677 // The above conversion succeeded
4678 return;
4679 }
4680
4681 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4682 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004683 return;
4684 }
4685
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004686 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004687}
4688
Laurence Lundbladec4537442020-04-14 18:53:22 -07004689
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004691 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004693void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004694 int64_t nLabel,
4695 uint32_t uConvertTypes,
4696 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697{
4698 QCBORItem Item;
4699
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004700 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701
4702 if(pMe->uLastError == QCBOR_SUCCESS) {
4703 // The above conversion succeeded
4704 return;
4705 }
4706
4707 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4708 // The above conversion failed in a way that code below can't correct
4709 return;
4710 }
4711
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004712 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004713}
4714
4715
4716/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004717 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004719void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004720 const char *szLabel,
4721 uint32_t uConvertTypes,
4722 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723{
4724 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004725 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726
4727 if(pMe->uLastError == QCBOR_SUCCESS) {
4728 // The above conversion succeeded
4729 return;
4730 }
4731
4732 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4733 // The above conversion failed in a way that code below can't correct
4734 return;
4735 }
4736
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004738}
4739
4740
Laurence Lundblade9b334962020-08-27 10:55:53 -07004741static QCBORError ConvertDouble(const QCBORItem *pItem,
4742 uint32_t uConvertTypes,
4743 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004744{
4745 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004746 case QCBOR_TYPE_FLOAT:
4747#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4748 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4749 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4750 *pdValue = (double)pItem->val.fnum;
4751 } else {
4752 return QCBOR_ERR_UNEXPECTED_TYPE;
4753 }
4754 }
4755#else
4756 return QCBOR_ERR_HW_FLOAT_DISABLED;
4757#endif
4758 break;
4759
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004761 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4762 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004763 *pdValue = pItem->val.dfnum;
4764 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766 }
4767 }
4768 break;
4769
4770 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004771#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004772 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004773 // TODO: how does this work?
4774 *pdValue = (double)pItem->val.int64;
4775
4776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004779#else
4780 return QCBOR_ERR_HW_FLOAT_DISABLED;
4781#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004782 break;
4783
4784 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004785#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 *pdValue = (double)pItem->val.uint64;
4788 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790 }
4791 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004792#else
4793 return QCBOR_ERR_HW_FLOAT_DISABLED;
4794#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795
4796 default:
4797 return QCBOR_ERR_UNEXPECTED_TYPE;
4798 }
4799
4800 return QCBOR_SUCCESS;
4801}
4802
4803
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004804void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004805 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004807 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004808{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004809 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004810 return;
4811 }
4812
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004813 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004814
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004815 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004816 if(uError) {
4817 pMe->uLastError = (uint8_t)uError;
4818 return;
4819 }
4820
4821 if(pItem) {
4822 *pItem = Item;
4823 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004824
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004825 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004826}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004827
Laurence Lundbladec4537442020-04-14 18:53:22 -07004828
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4830 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 double *pdValue,
4833 QCBORItem *pItem)
4834{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004835 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004836 if(pMe->uLastError != QCBOR_SUCCESS) {
4837 return;
4838 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004840 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841}
4842
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004843
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4845 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004846 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847 double *pdValue,
4848 QCBORItem *pItem)
4849{
4850 if(pMe->uLastError != QCBOR_SUCCESS) {
4851 return;
4852 }
4853
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004854 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004855 if(pMe->uLastError != QCBOR_SUCCESS) {
4856 return;
4857 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860}
4861
4862
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004863#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004864static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4865{
4866 double dResult;
4867
4868 dResult = 0.0;
4869 const uint8_t *pByte = BigNum.ptr;
4870 size_t uLen = BigNum.len;
4871 /* This will overflow and become the float value INFINITY if the number
4872 is too large to fit. No error will be logged.
4873 TODO: should an error be logged? */
4874 while(uLen--) {
4875 dResult = (dResult * 256.0) + (double)*pByte++;
4876 }
4877
4878 return dResult;
4879}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004880#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4881
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004882
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004883static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004884{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004885#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004886 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004887 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4888
4889 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004890 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004891
4892#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895 // TODO: rounding and overflow errors
4896 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4897 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4898 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004900 }
4901 break;
4902
4903 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004904 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4906 exp2((double)pItem->val.expAndMantissa.nExponent);
4907 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004908 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004909 }
4910 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004911#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912
4913 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004914 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004915 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4916 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004917 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004918 }
4919 break;
4920
4921 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004922 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004923 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004924 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926 }
4927 break;
4928
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004929#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004931 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004932 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4933 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4934 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004935 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004936 }
4937 break;
4938
4939 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004940 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004941 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4942 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4943 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004944 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004945 }
4946 break;
4947
4948 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004949 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004950 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4951 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4952 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004953 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004954 }
4955 break;
4956
4957 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004958 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004959 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4961 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004962 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963 }
4964 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004965#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4966
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004967
4968 default:
4969 return QCBOR_ERR_UNEXPECTED_TYPE;
4970 }
4971
4972 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004973
4974#else
4975 (void)pItem;
4976 (void)uConvertTypes;
4977 (void)pdValue;
4978 return QCBOR_ERR_HW_FLOAT_DISABLED;
4979#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4980
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004981}
4982
4983
4984/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004985 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004987void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4988 uint32_t uConvertTypes,
4989 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004990{
4991
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004992 QCBORItem Item;
4993
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004994 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004995
4996 if(pMe->uLastError == QCBOR_SUCCESS) {
4997 // The above conversion succeeded
4998 return;
4999 }
5000
5001 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5002 // The above conversion failed in a way that code below can't correct
5003 return;
5004 }
5005
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005006 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005007}
5008
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005009
5010/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005011 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005012*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005013void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5014 int64_t nLabel,
5015 uint32_t uConvertTypes,
5016 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005017{
5018 QCBORItem Item;
5019
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005020 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005021
5022 if(pMe->uLastError == QCBOR_SUCCESS) {
5023 // The above conversion succeeded
5024 return;
5025 }
5026
5027 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5028 // The above conversion failed in a way that code below can't correct
5029 return;
5030 }
5031
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005032 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005033}
5034
5035
5036/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005037 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005038*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005039void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5040 const char *szLabel,
5041 uint32_t uConvertTypes,
5042 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005043{
5044 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005045 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005046
5047 if(pMe->uLastError == QCBOR_SUCCESS) {
5048 // The above conversion succeeded
5049 return;
5050 }
5051
5052 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5053 // The above conversion failed in a way that code below can't correct
5054 return;
5055 }
5056
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005057 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005058}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005059
5060
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005061
5062
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005063#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005064static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5065{
5066 while((uInt & 0xff00000000000000UL) == 0) {
5067 uInt = uInt << 8;
5068 };
5069
5070 UsefulOutBuf UOB;
5071
5072 UsefulOutBuf_Init(&UOB, Buffer);
5073
5074 while(uInt) {
5075 const uint64_t xx = uInt & 0xff00000000000000UL;
5076 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5077 uInt = uInt << 8;
5078 (void)xx;
5079 }
5080
5081 return UsefulOutBuf_OutUBuf(&UOB);
5082}
5083
5084
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005085static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5086 TagSpecification TagSpec,
5087 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005088{
5089 QCBORError uErr;
5090 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005091 while(1) {
5092 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
5093 if(uErr != QCBOR_SUCCESS) {
5094 goto Done;
5095 }
5096
5097 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5098 break; // Successful exit. Moving on to finish decoding.
5099 }
5100
5101 // The item is an array, which means an undecoded
5102 // mantissa and exponent, so decode it. It will then
5103 // have a different type and exit the loop if.
5104 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5105 if(uErr != QCBOR_SUCCESS) {
5106 goto Done;
5107 }
5108
5109 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005110 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005111 }
5112Done:
5113 return uErr;
5114}
5115
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005116
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005117static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 TagSpecification TagSpec,
5119 QCBORItem *pItem,
5120 int64_t *pnMantissa,
5121 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005122{
5123 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005124
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005125 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005126 if(uErr != QCBOR_SUCCESS) {
5127 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005128 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005129
Laurence Lundblade9b334962020-08-27 10:55:53 -07005130 switch (pItem->uDataType) {
5131
5132 case QCBOR_TYPE_DECIMAL_FRACTION:
5133 case QCBOR_TYPE_BIGFLOAT:
5134 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5135 *pnExponent = pItem->val.expAndMantissa.nExponent;
5136 break;
5137
5138 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5139 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5140 *pnExponent = pItem->val.expAndMantissa.nExponent;
5141 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5142 break;
5143
5144 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5145 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5146 *pnExponent = pItem->val.expAndMantissa.nExponent;
5147 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5148 break;
5149
5150 default:
5151 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5152 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005153
5154 Done:
5155 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005156}
5157
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005158
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005159static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005160 TagSpecification TagSpec,
5161 QCBORItem *pItem,
5162 UsefulBuf BufferForMantissa,
5163 UsefulBufC *pMantissa,
5164 bool *pbIsNegative,
5165 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005166{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005167 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005168
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005169 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005170 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005171 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005172 }
5173
5174 uint64_t uMantissa;
5175
5176 switch (pItem->uDataType) {
5177
5178 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005179 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005180 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5181 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5182 *pbIsNegative = false;
5183 } else {
5184 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5185 *pbIsNegative = true;
5186 }
5187 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5188 *pnExponent = pItem->val.expAndMantissa.nExponent;
5189 break;
5190
5191 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005192 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005193 *pnExponent = pItem->val.expAndMantissa.nExponent;
5194 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5195 *pbIsNegative = false;
5196 break;
5197
5198 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005199 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005200 *pnExponent = pItem->val.expAndMantissa.nExponent;
5201 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5202 *pbIsNegative = true;
5203 break;
5204
5205 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005206 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005207 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005208
5209Done:
5210 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005211}
5212
5213
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005214/*
5215 Public function, see header qcbor/qcbor_decode.h file
5216*/
5217void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5218 uint8_t uTagRequirement,
5219 int64_t *pnMantissa,
5220 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005221{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005222 if(pMe->uLastError != QCBOR_SUCCESS) {
5223 return;
5224 }
5225
5226 QCBORItem Item;
5227 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5228 if(uError) {
5229 pMe->uLastError = (uint8_t)uError;
5230 return;
5231 }
5232
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005233 const TagSpecification TagSpec =
5234 {
5235 uTagRequirement,
5236 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5237 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5238 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005239
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005240 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005241}
5242
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005243
5244/*
5245 Public function, see header qcbor/qcbor_decode.h file
5246*/
5247void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005248 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005249 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005250 int64_t *pnMantissa,
5251 int64_t *pnExponent)
5252{
5253 if(pMe->uLastError != QCBOR_SUCCESS) {
5254 return;
5255 }
5256
5257 QCBORItem Item;
5258 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5259
5260 const TagSpecification TagSpec =
5261 {
5262 uTagRequirement,
5263 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5264 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5265 };
5266
5267 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5268}
5269
5270
5271/*
5272 Public function, see header qcbor/qcbor_decode.h file
5273*/
5274void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005275 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005276 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005277 int64_t *pnMantissa,
5278 int64_t *pnExponent)
5279{
5280 if(pMe->uLastError != QCBOR_SUCCESS) {
5281 return;
5282 }
5283
5284 QCBORItem Item;
5285 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5286
5287 const TagSpecification TagSpec =
5288 {
5289 uTagRequirement,
5290 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5291 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5292 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005293
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005294 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5295}
5296
5297
5298/*
5299 Public function, see header qcbor/qcbor_decode.h file
5300*/
5301void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5302 uint8_t uTagRequirement,
5303 UsefulBuf MantissaBuffer,
5304 UsefulBufC *pMantissa,
5305 bool *pbMantissaIsNegative,
5306 int64_t *pnExponent)
5307{
5308 if(pMe->uLastError != QCBOR_SUCCESS) {
5309 return;
5310 }
5311
5312 QCBORItem Item;
5313 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5314 if(uError) {
5315 pMe->uLastError = (uint8_t)uError;
5316 return;
5317 }
5318
5319 const TagSpecification TagSpec =
5320 {
5321 uTagRequirement,
5322 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5323 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5324 };
5325
5326 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5327}
5328
5329
5330/*
5331 Public function, see header qcbor/qcbor_decode.h file
5332*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005333void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005334 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005335 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005336 UsefulBuf BufferForMantissa,
5337 UsefulBufC *pMantissa,
5338 bool *pbIsNegative,
5339 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005340{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 if(pMe->uLastError != QCBOR_SUCCESS) {
5342 return;
5343 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005344
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005345 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005346 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005347 if(pMe->uLastError != QCBOR_SUCCESS) {
5348 return;
5349 }
5350
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005351 const TagSpecification TagSpec =
5352 {
5353 uTagRequirement,
5354 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5355 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5356 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005357
5358 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005359}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005360
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005361
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005362/*
5363 Public function, see header qcbor/qcbor_decode.h file
5364*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005365void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005366 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005367 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005368 UsefulBuf BufferForMantissa,
5369 UsefulBufC *pMantissa,
5370 bool *pbIsNegative,
5371 int64_t *pnExponent)
5372{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005373 if(pMe->uLastError != QCBOR_SUCCESS) {
5374 return;
5375 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005376
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005377 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005378 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5379 if(pMe->uLastError != QCBOR_SUCCESS) {
5380 return;
5381 }
5382
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005383 const TagSpecification TagSpec =
5384 {
5385 uTagRequirement,
5386 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5387 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5388 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005389
5390 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5391}
5392
5393
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005394/*
5395 Public function, see header qcbor/qcbor_decode.h file
5396*/
5397void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5398 uint8_t uTagRequirement,
5399 int64_t *pnMantissa,
5400 int64_t *pnExponent)
5401{
5402 if(pMe->uLastError != QCBOR_SUCCESS) {
5403 return;
5404 }
5405
5406 QCBORItem Item;
5407 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5408 if(uError) {
5409 pMe->uLastError = (uint8_t)uError;
5410 return;
5411 }
5412 const TagSpecification TagSpec =
5413 {
5414 uTagRequirement,
5415 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5416 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5417 };
5418
5419 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5420}
5421
5422
5423/*
5424 Public function, see header qcbor/qcbor_decode.h file
5425*/
5426void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005427 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005428 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005429 int64_t *pnMantissa,
5430 int64_t *pnExponent)
5431{
5432 if(pMe->uLastError != QCBOR_SUCCESS) {
5433 return;
5434 }
5435
5436 QCBORItem Item;
5437 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5438 if(pMe->uLastError != QCBOR_SUCCESS) {
5439 return;
5440 }
5441
5442 const TagSpecification TagSpec =
5443 {
5444 uTagRequirement,
5445 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5446 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5447 };
5448
5449 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5450}
5451
5452
5453/*
5454 Public function, see header qcbor/qcbor_decode.h file
5455*/
5456void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005457 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005458 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005459 int64_t *pnMantissa,
5460 int64_t *pnExponent)
5461{
5462 if(pMe->uLastError != QCBOR_SUCCESS) {
5463 return;
5464 }
5465
5466 QCBORItem Item;
5467 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5468 if(pMe->uLastError != QCBOR_SUCCESS) {
5469 return;
5470 }
5471
5472 const TagSpecification TagSpec =
5473 {
5474 uTagRequirement,
5475 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5476 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5477 };
5478
5479 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5480}
5481
5482
5483/*
5484 Public function, see header qcbor/qcbor_decode.h file
5485*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005486void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5487 uint8_t uTagRequirement,
5488 UsefulBuf MantissaBuffer,
5489 UsefulBufC *pMantissa,
5490 bool *pbMantissaIsNegative,
5491 int64_t *pnExponent)
5492{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005493 if(pMe->uLastError != QCBOR_SUCCESS) {
5494 return;
5495 }
5496
5497 QCBORItem Item;
5498 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5499 if(uError) {
5500 pMe->uLastError = (uint8_t)uError;
5501 return;
5502 }
5503
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 const TagSpecification TagSpec =
5505 {
5506 uTagRequirement,
5507 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5508 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5509 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005510
5511 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005512}
5513
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005514
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005515/*
5516 Public function, see header qcbor/qcbor_decode.h file
5517*/
5518void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005519 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005520 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005521 UsefulBuf BufferForMantissa,
5522 UsefulBufC *pMantissa,
5523 bool *pbIsNegative,
5524 int64_t *pnExponent)
5525{
5526 if(pMe->uLastError != QCBOR_SUCCESS) {
5527 return;
5528 }
5529
5530 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005531 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5532 if(pMe->uLastError != QCBOR_SUCCESS) {
5533 return;
5534 }
5535
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005536 const TagSpecification TagSpec =
5537 {
5538 uTagRequirement,
5539 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5540 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5541 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005542
5543 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5544}
5545
5546
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005547/*
5548 Public function, see header qcbor/qcbor_decode.h file
5549*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005550void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005551 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005552 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005553 UsefulBuf BufferForMantissa,
5554 UsefulBufC *pMantissa,
5555 bool *pbIsNegative,
5556 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005557{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005558 if(pMe->uLastError != QCBOR_SUCCESS) {
5559 return;
5560 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005561
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005562 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005563 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5564 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005565 return;
5566 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005567
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005568 const TagSpecification TagSpec =
5569 {
5570 uTagRequirement,
5571 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5572 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5573 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005574
5575 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005576}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005577
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005578#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */