blob: 34d4dbc79c00c98f8276cc1ba31d588692ed3b61 [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 Lundblade12d32c52018-09-19 11:25:27 -070036#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053039/*
40 This casts away the const-ness of a pointer, usually so it can be
41 freed or realloced.
42 */
43#define UNCONST_POINTER(ptr) ((void *)(ptr))
44
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundblade02625d42020-06-25 14:41:41 -070047inline static bool
48// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
49QCBORItem_IsMapOrArray(const QCBORItem *pMe)
50{
51 const uint8_t uDataType = pMe->uDataType;
52 return uDataType == QCBOR_TYPE_MAP ||
53 uDataType == QCBOR_TYPE_ARRAY ||
54 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
55}
56
57inline static bool
58QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
59{
60 if(!QCBORItem_IsMapOrArray(pMe)){
61 return false;
62 }
63
64 if(pMe->val.uCount != 0) {
65 return false;
66 }
67 return true;
68}
69
70inline static bool
71QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
72{
73 if(!QCBORItem_IsMapOrArray(pMe)){
74 return false;
75 }
76
77 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
78 return false;
79 }
80 return true;
81}
82
83
Laurence Lundbladeee851742020-01-08 08:37:05 -080084/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070085 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080086 ===========================================================================*/
87
Laurence Lundblade9c905e82020-04-25 11:31:38 -070088/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070089 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
90 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070091
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092
Laurence Lundblade9c905e82020-04-25 11:31:38 -070093
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094 */
95
Laurence Lundblade24d509a2020-06-06 18:43:15 -070096
97inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -070098DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700100 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700101 /*
102 Limit in DecodeNesting_Descend against more than
103 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
104 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700105 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700106}
107
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700108
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700109inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700110DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700111{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700112 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700113 /*
114 Limit in DecodeNesting_Descend against more than
115 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
116 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700117 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700118}
119
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700120
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700121static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700122DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123{
124 return pNesting->pCurrentBounded->u.ma.uStartOffset;
125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade085d7952020-07-24 10:26:30 -0700128static inline bool
129DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
130{
131 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
132 return true;
133 } else {
134 return false;
135 }
136}
137
138
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700139inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700140DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700142 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143 return true;
144 } else {
145 return false;
146 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700147}
148
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700149
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700150inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700151DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152{
153 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155 return false;
156 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700157 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159 return false;
160 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return true;
163}
164
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700165
Laurence Lundblade642282a2020-06-23 12:00:33 -0700166inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700167DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700168{
169 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171 return true;
172 }
173 return false;
174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700177inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178{
179 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
180 return true;
181 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700182 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700183 return true;
184 }
185 return false;
186}
187
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700188
Laurence Lundblade085d7952020-07-24 10:26:30 -0700189inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190{
191 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700192 /*
193 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
194 larger than DecodeNesting_EnterBoundedMode which keeps it less than
195 uin32_t so the cast is safe.
196 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700197 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700198
199 if(bIsEmpty) {
200 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
201 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700205inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700207 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208}
209
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700210
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700213{
214 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216 return false;
217 }
218 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220 return false;
221 }
222 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224 return false;
225 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700226 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229 return false;
230 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700231 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return true;
233}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700234
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700236inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700237DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700238{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
241 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700242 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700243 return false;
244 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700245}
246
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700247
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700248inline static bool
249DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700250{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700251 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
252 return true;
253 } else {
254 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700255 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256}
257
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700258
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700259inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700260DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700261{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700262 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700263 return false;
264 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700265
266 if(pNesting->pCurrentBounded->uLevelType != uType) {
267 return false;
268 }
269
270 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700271}
272
Laurence Lundblade02625d42020-06-25 14:41:41 -0700273
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700274inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700275DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700276{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700277 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700278 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700279}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700280
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700281
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700282inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700283DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
284{
285 // Only call on a defnite length array / map
286 pNesting->pCurrent->u.ma.uCountCursor++;
287}
288
289
290inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700291DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
292{
293 pNesting->pCurrent--;
294}
295
Laurence Lundblade02625d42020-06-25 14:41:41 -0700296
297static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700298DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700299{
300 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700301 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700302 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
303 }
304
305 // The actual descend
306 pNesting->pCurrent++;
307
308 pNesting->pCurrent->uLevelType = uType;
309
310 return QCBOR_SUCCESS;
311}
312
313
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700314inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700315DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700316{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700317 /*
318 Should only be called on map/array.
319
320 Have descended into this before this is called. The job here is
321 just to mark it in bounded mode.
322 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700323 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700324 return QCBOR_ERR_BUFFER_TOO_LARGE;
325 }
326
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700327 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700328
329 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700330
331 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700332}
333
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700334
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700335inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700336DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700337 uint8_t uQCBORType,
338 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700340 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341
342 if(uCount == 0) {
343 // Nothing to do for empty definite lenth arrays. They are just are
344 // effectively the same as an item that is not a map or array
345 goto Done;
346 // Empty indefinite length maps and arrays are handled elsewhere
347 }
348
349 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
351 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
352 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700353 goto Done;
354 }
355
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700356 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358 goto Done;
359 }
360
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700361 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700362 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
363 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700364
365 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700366
367Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700368 return uError;;
369}
370
371
372static inline void
373DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
374{
375 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
376}
377
378
379static inline void
380DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
381{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700382 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700383 pNesting->pCurrentBounded--;
384 if(DecodeNesting_IsCurrentBounded(pNesting)) {
385 break;
386 }
387 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700388}
389
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700390static inline void
391DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
392{
393 pNesting->pCurrent = pNesting->pCurrentBounded;
394}
395
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700396
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700397inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700398DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700399 uint32_t uEndOffset,
400 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700401{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700403
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700404 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700406 goto Done;
407 }
408
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700410 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
411 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700412
Laurence Lundblade02625d42020-06-25 14:41:41 -0700413 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700414 pNesting->pCurrentBounded = pNesting->pCurrent;
415
416Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 return uError;;
418}
419
Laurence Lundbladed0304932020-06-27 10:59:38 -0700420
421static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700422DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423{
424 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700425}
426
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700427
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700432 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
433 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434}
435
436
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700437inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700439{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700440 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700441 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700443}
444
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700445
Laurence Lundblade02625d42020-06-25 14:41:41 -0700446static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700447DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700448{
449 *pNesting = *pSave;
450}
451
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700454DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700455{
456 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
457}
458
459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462{
463 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
464}
465
466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700468
469const char *TypeStr(uint8_t type)
470{
471 switch(type) {
472 case QCBOR_TYPE_MAP: return " map";
473 case QCBOR_TYPE_ARRAY: return "array";
474 case QCBOR_TYPE_BYTE_STRING: return " bstr";
475 default: return " --- ";
476 }
477}
478
479static char buf[20]; // Not thread safe, but that is OK
480const char *CountString(uint16_t uCount, uint16_t uTotal)
481{
482 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
483 strcpy(buf, "indefinite");
484 } else {
485 sprintf(buf, "%d/%d", uCount, uTotal);
486 }
487 return buf;
488}
489
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700490
Laurence Lundblade02625d42020-06-25 14:41:41 -0700491void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700492{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700493#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495 szName,
496 (uint32_t)pBuf->cursor,
497 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498
499 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700501 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700502 break;
503 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700504
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700505 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700506 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700507 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700508 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700509
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700511 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512 pNesting->pLevels[i].u.bs.uEndOfBstr,
513 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700514
515 } else {
516 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700517 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
518 pNesting->pLevels[i].u.ma.uCountTotal));
519 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
520 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700521 }
522 }
523
524 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700525 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700526 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700527#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700528}
529
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800533 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
534
535 The following four functions are pretty wrappers for invocation of
536 the string allocator supplied by the caller.
537
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800539
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540static inline void
541StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542{
543 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
544}
545
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546// StringAllocator_Reallocate called with pMem NULL is
547// equal to StringAllocator_Allocate()
548static inline UsefulBuf
549StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
550 void *pMem,
551 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552{
553 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
554}
555
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556static inline UsefulBuf
557StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558{
559 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
560}
561
Laurence Lundbladeee851742020-01-08 08:37:05 -0800562static inline void
563StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800564{
565 if(pMe->pfAllocator) {
566 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
567 }
568}
569
570
571
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572/*===========================================================================
573 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800575 See qcbor/qcbor_decode.h for definition of the object
576 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578/*
579 Public function, see header file
580 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581void QCBORDecode_Init(QCBORDecodeContext *me,
582 UsefulBufC EncodedCBOR,
583 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584{
585 memset(me, 0, sizeof(QCBORDecodeContext));
586 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 // Don't bother with error check on decode mode. If a bad value is
588 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700589 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700590 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700591 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700592 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700593 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700594}
595
596
597/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598 Public function, see header file
599 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
601 QCBORStringAllocate pfAllocateFunction,
602 void *pAllocateContext,
603 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
606 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
607 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700608}
609
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610
611/*
612 Public function, see header file
613 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700614void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800615 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700616{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700617 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700618 (void)pMe;
619 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700620}
621
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622
623/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 This decodes the fundamental part of a CBOR data item, the type and
625 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 This does the network->host byte order conversion. The conversion
630 here also results in the conversion for floats in addition to that
631 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700633 This returns:
634 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800635
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800637 tags and floats and length for strings and arrays
638
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800640 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800641
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800642 The int type is preferred to uint8_t for some variables as this
643 avoids integer promotions, can reduce code size and makes
644 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
647 int *pnMajorType,
648 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700651 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800652
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800654 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800657 const int nTmpMajorType = nInitialByte >> 5;
658 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800660 // Where the number or argument accumulates
661 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800662
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700664 // Need to get 1,2,4 or 8 additional argument bytes. Map
665 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800666 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800668 // Loop getting all the bytes in the argument
669 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800671 // This shift and add gives the endian conversion
672 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
673 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 // The reserved and thus-far unused additional info values
676 nReturn = QCBOR_ERR_UNSUPPORTED;
677 goto Done;
678 } else {
679 // Less than 24, additional info is argument or 31, an indefinite length
680 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 if(UsefulInputBuf_GetError(pUInBuf)) {
685 nReturn = QCBOR_ERR_HIT_END;
686 goto Done;
687 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 // All successful if we got here.
690 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800691 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800692 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695Done:
696 return nReturn;
697}
698
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701 CBOR doesn't explicitly specify two's compliment for integers but all
702 CPUs use it these days and the test vectors in the RFC are so. All
703 integers in the CBOR structure are positive and the major type
704 indicates positive or negative. CBOR can express positive integers
705 up to 2^x - 1 where x is the number of bits and negative integers
706 down to 2^x. Note that negative numbers can be one more away from
707 zero than positive. Stdint, as far as I can tell, uses two's
708 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 used carefully here, and in particular why it isn't used in the interface.
712 Also see
713 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
714
715 Int is used for values that need less than 16-bits and would be subject
716 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800718inline static QCBORError
719DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700721 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
724 if (uNumber <= INT64_MAX) {
725 pDecodedItem->val.int64 = (int64_t)uNumber;
726 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800727
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728 } else {
729 pDecodedItem->val.uint64 = uNumber;
730 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 }
733 } else {
734 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800735 // CBOR's representation of negative numbers lines up with the
736 // two-compliment representation. A negative integer has one
737 // more in range than a positive integer. INT64_MIN is
738 // equal to (-INT64_MAX) - 1.
739 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 } else {
743 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000744 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745 nReturn = QCBOR_ERR_INT_OVERFLOW;
746 }
747 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800748
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749 return nReturn;
750}
751
752// Make sure #define value line up as DecodeSimple counts on this.
753#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
754#error QCBOR_TYPE_FALSE macro value wrong
755#endif
756
757#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
758#error QCBOR_TYPE_TRUE macro value wrong
759#endif
760
761#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
762#error QCBOR_TYPE_NULL macro value wrong
763#endif
764
765#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
766#error QCBOR_TYPE_UNDEF macro value wrong
767#endif
768
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700769#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
770#error QCBOR_TYPE_BREAK macro value wrong
771#endif
772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
774#error QCBOR_TYPE_DOUBLE macro value wrong
775#endif
776
777#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
778#error QCBOR_TYPE_FLOAT macro value wrong
779#endif
780
781/*
782 Decode true, false, floats, break...
783 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800784inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800785DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700786{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700787 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800790 // above make sure uAdditionalInfo values line up with uDataType values.
791 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
792 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800795 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
796 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700798 case HALF_PREC_FLOAT:
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700799#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700801 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700802 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
804 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700805#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700806 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700807#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700808 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700809 case SINGLE_PREC_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700810 // Single precision is normally returned as a double
811 // since double is widely supported, there is no loss of
812 // precision, it makes it easy for the caller in
813 // most cases and it can be converted back to single
814 // with no loss of precision
815 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700816 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700817 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700818 {
819 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
820#ifndef QCBOR_DISABLE_FLOAT_HW_USE
821 // In the normal case, use HW to convert float to double.
822 pDecodedItem->val.dfnum = (double)f;
823 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700824#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700825 // Use of float HW is disabled, return as a float.
826 pDecodedItem->val.fnum = f;
827 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
828
829 // IEEE754_FloatToDouble() could be used here to return
830 // as a double, but it adds object code and most likely
831 // anyone disabling FLOAT HW use doesn't care about
832 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700833#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700834 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700835 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700836
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700837 case DOUBLE_PREC_FLOAT:
838 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700839 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700840 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700842 case CBOR_SIMPLEV_FALSE: // 20
843 case CBOR_SIMPLEV_TRUE: // 21
844 case CBOR_SIMPLEV_NULL: // 22
845 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700846 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800848
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849 case CBOR_SIMPLEV_ONEBYTE: // 24
850 if(uNumber <= CBOR_SIMPLE_BREAK) {
851 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700852 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700853 goto Done;
854 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800855 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700856 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800857
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 default: // 0-19
859 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800860 /*
861 DecodeTypeAndNumber will make uNumber equal to
862 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
863 safe because the 2, 4 and 8 byte lengths of uNumber are in
864 the double/float cases above
865 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700866 pDecodedItem->val.uSimple = (uint8_t)uNumber;
867 break;
868 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800869
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870Done:
871 return nReturn;
872}
873
874
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530876 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800878inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
879 int nMajorType,
880 uint64_t uStrLen,
881 UsefulInputBuf *pUInBuf,
882 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700883{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700884 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
887 // This check makes the casts to size_t below safe.
888
889 // 4 bytes less than the largest sizeof() so this can be tested by
890 // putting a SIZE_MAX length in the CBOR test input (no one will
891 // care the limit on strings is 4 bytes shorter).
892 if(uStrLen > SIZE_MAX-4) {
893 nReturn = QCBOR_ERR_STRING_TOO_LONG;
894 goto Done;
895 }
896
897 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530898 if(UsefulBuf_IsNULLC(Bytes)) {
899 // Failed to get the bytes for this string item
900 nReturn = QCBOR_ERR_HIT_END;
901 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530903
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800904 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530905 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800906 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530907 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700908 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530909 goto Done;
910 }
911 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800912 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530913 } else {
914 // Normal case with no string allocator
915 pDecodedItem->val.string = Bytes;
916 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800918 // Cast because ternary operator causes promotion to integer
919 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
920 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800921
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530922Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923 return nReturn;
924}
925
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700926
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700928
929
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930
931
Laurence Lundbladeee851742020-01-08 08:37:05 -0800932// Make sure the constants align as this is assumed by
933// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
935#error QCBOR_TYPE_ARRAY value not lined up with major type
936#endif
937#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
938#error QCBOR_TYPE_MAP value not lined up with major type
939#endif
940
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800942 This gets a single data item and decodes it including preceding
943 optional tagging. This does not deal with arrays and maps and nesting
944 except to decode the data item introducing them. Arrays and maps are
945 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundbladeee851742020-01-08 08:37:05 -0800947 Errors detected here include: an array that is too long to decode,
948 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800950static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
951 QCBORItem *pDecodedItem,
952 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700954 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladeee851742020-01-08 08:37:05 -0800956 /*
957 Get the major type and the number. Number could be length of more
958 bytes or the value depending on the major type nAdditionalInfo is
959 an encoding of the length of the uNumber and is needed to decode
960 floats and doubles
961 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800962 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800965
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700966 memset(pDecodedItem, 0, sizeof(QCBORItem));
967
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800968 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundbladeee851742020-01-08 08:37:05 -0800970 // Error out here if we got into trouble on the type and number. The
971 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700972 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700973 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700974 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800975
Laurence Lundbladeee851742020-01-08 08:37:05 -0800976 // At this point the major type and the value are valid. We've got
977 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800978 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
980 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800981 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700982 nReturn = QCBOR_ERR_BAD_INT;
983 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700985 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800987
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
989 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800990 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
991 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
992 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
993 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530994 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700997 }
998 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1001 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1002 // Record the number of items in the array or map
1003 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
1004 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1005 goto Done;
1006 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001008 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001010 // type conversion OK because of check above
1011 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001013 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1015 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001019 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001020 nReturn = QCBOR_ERR_BAD_INT;
1021 } else {
1022 pDecodedItem->val.uTagV = uNumber;
1023 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
1024 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundbladeee851742020-01-08 08:37:05 -08001027 case CBOR_MAJOR_TYPE_SIMPLE:
1028 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001029 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001031
Laurence Lundbladeee851742020-01-08 08:37:05 -08001032 default:
1033 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001034 nReturn = QCBOR_ERR_UNSUPPORTED;
1035 break;
1036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001037
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038Done:
1039 return nReturn;
1040}
1041
1042
1043
1044/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001045 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001046 individual chunk items together into one QCBORItem using the string
1047 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301049 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001051static inline QCBORError
1052GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001054 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001055
1056 // Get pointer to string allocator. First use is to pass it to
1057 // GetNext_Item() when option is set to allocate for *every* string.
1058 // Second use here is to allocate space to coallese indefinite
1059 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001060 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1061 &(me->StringAllocator) :
1062 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001064 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001065 nReturn = GetNext_Item(&(me->InBuf),
1066 pDecodedItem,
1067 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068 if(nReturn) {
1069 goto Done;
1070 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001071
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301073 // code in this function from here down can be eliminated. Run tests, except
1074 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001076 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001077 const uint8_t uStringType = pDecodedItem->uDataType;
1078 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001079 goto Done; // no need to do any work here on non-string types
1080 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001082 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301083 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001084 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001088 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1090 goto Done;
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001093 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001094 UsefulBufC FullString = NULLUsefulBufC;
1095
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001097 // Get item for next chunk
1098 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001099 // NULL string allocator passed here. Do not need to allocate
1100 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001101 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001103 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301106 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001107 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001108 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001109 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301110 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 break;
1112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001114 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301115 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001116 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001117 if(StringChunkItem.uDataType != uStringType ||
1118 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001119 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 break;
1121 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001122
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301123 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001124 // The first time throurgh FullString.ptr is NULL and this is
1125 // equivalent to StringAllocator_Allocate()
1126 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1127 UNCONST_POINTER(FullString.ptr),
1128 FullString.len + StringChunkItem.val.string.len);
1129
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301131 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001132 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 break;
1134 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001135
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001136 // Copy new string chunk at the end of string so far.
1137 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001140 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1141 // Getting the item failed, clean up the allocated memory
1142 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001143 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001144
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001145Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146 return nReturn;
1147}
1148
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001149
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001150static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1151 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001152 return uTagVal;
1153 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001154 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001155 return me->auMappedTags[x];
1156 }
1157}
1158
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001159/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001160 Gets all optional tag data items preceding a data item that is not an
1161 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001162 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001163static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001164GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001165{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001166 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001167
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001168 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1169 CBOR_TAG_INVALID16,
1170 CBOR_TAG_INVALID16,
1171 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001172
Laurence Lundblade59289e52019-12-30 13:44:37 -08001173 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001174 for(;;) {
1175 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001177 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001180 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1181 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001182 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001183 break;
1184 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001185
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186 // Is there room for the tag in the tags list?
1187 size_t uTagIndex;
1188 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001189 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001190 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001191 }
1192 }
1193 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001194 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001196
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001197 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001198 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001199 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001200 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001201 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001202 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001203 break;
1204 }
1205 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001206 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 break;
1208 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001209 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001210 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1211 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001212 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1213 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 }
1215
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001216 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001218 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219
1220 } else {
1221 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001222 }
1223 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001224
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001225Done:
1226 return nReturn;
1227}
1228
1229
1230/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001231 This layer takes care of map entries. It combines the label and data
1232 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001233 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001234static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001235GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001236{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001237 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001239 if(nReturn)
1240 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001241
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001242 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001243 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001244 goto Done;
1245 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001246
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001247 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1248 // In a map and caller wants maps decoded, not treated as arrays
1249
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001250 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001251 // If in a map and the right decoding mode, get the label
1252
Laurence Lundbladeee851742020-01-08 08:37:05 -08001253 // Save label in pDecodedItem and get the next which will
1254 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001255 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001256 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001257 if(nReturn)
1258 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001259
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301260 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001261
1262 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1263 // strings are always good labels
1264 pDecodedItem->label.string = LabelItem.val.string;
1265 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1266 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001267 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001268 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1269 goto Done;
1270 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1271 pDecodedItem->label.int64 = LabelItem.val.int64;
1272 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1273 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1274 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1275 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1276 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1277 pDecodedItem->label.string = LabelItem.val.string;
1278 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1279 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1280 } else {
1281 // label is not an int or a string. It is an arrray
1282 // or a float or such and this implementation doesn't handle that.
1283 // Also, tags on labels are ignored.
1284 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1285 goto Done;
1286 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001287 }
1288 } else {
1289 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001290 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1291 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1292 goto Done;
1293 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001294 // Decoding a map as an array
1295 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001296 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1297 // Cast is needed because of integer promotion
1298 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001299 }
1300 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001301
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001302Done:
1303 return nReturn;
1304}
1305
1306
Laurence Lundblade02625d42020-06-25 14:41:41 -07001307/*
1308 See if next item is a CBOR break. If it is, it is consumed,
1309 if not it is not consumed.
1310*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001311static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001312NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1313{
1314 *pbNextIsBreak = false;
1315 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001316 QCBORItem Peek;
1317 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1318 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1319 if(uReturn != QCBOR_SUCCESS) {
1320 return uReturn;
1321 }
1322 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001323 // It is not a break, rewind so it can be processed normally.
1324 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001325 } else {
1326 *pbNextIsBreak = true;
1327 }
1328 }
1329
1330 return QCBOR_SUCCESS;
1331}
1332
1333
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001334/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001335 An item was just consumed, now figure out if it was the
1336 end of an array or map that can be closed out. That
1337 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001338*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001339static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001340{
1341 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001342
Laurence Lundblade642282a2020-06-23 12:00:33 -07001343 /* This loops ascending nesting levels as long as there is ascending to do */
1344 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1345
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001346 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001347 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001348 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1349 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001350 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001351 break;
1352 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001353 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001354
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001355 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001356 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001357 bool bIsBreak = false;
1358 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1359 if(uReturn != QCBOR_SUCCESS) {
1360 goto Done;
1361 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001362
1363 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001364 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001365 break;
1366 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001367
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001368 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001369 /*
1370 Break occurred inside a bstr-wrapped CBOR or
1371 in the top level sequence. This is always an
1372 error because neither are an indefinte length
1373 map/array.
1374 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001375 uReturn = QCBOR_ERR_BAD_BREAK;
1376 goto Done;
1377 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001378
Laurence Lundblade02625d42020-06-25 14:41:41 -07001379 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001380 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001381
Laurence Lundblade02625d42020-06-25 14:41:41 -07001382 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001383
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001384 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001385 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001386 /* 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 -07001387 if(bMarkEnd) {
1388 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001389 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001390
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001391 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001392 break;
1393 }
1394
1395 /* Finally, actually ascend one level. */
1396 DecodeNesting_Ascend(&(pMe->nesting));
1397 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001398
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001399 uReturn = QCBOR_SUCCESS;
1400
1401Done:
1402 return uReturn;
1403}
1404
1405
1406/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001407 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1409 indefinte length maps and arrays by looking at the item count or
1410 finding CBOR breaks. It detects the ends of the top-level sequence
1411 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001412 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001413static QCBORError
1414QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001415{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001416 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001417 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001418
Laurence Lundblade642282a2020-06-23 12:00:33 -07001419 /*
1420 If out of bytes to consume, it is either the end of the top-level
1421 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001422
Laurence Lundblade642282a2020-06-23 12:00:33 -07001423 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1424 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1425 CBOR is exited, the length is set back to the top-level's length
1426 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001428 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001429 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001430 goto Done;
1431 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001432
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433 /*
1434 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001435 array. The check for the end of an indefinite length array is
1436 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001437 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001438 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001439 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001440 goto Done;
1441 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001442
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001443 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001444 uReturn = GetNext_MapEntry(me, pDecodedItem);
1445 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001446 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001447 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301448
Laurence Lundblade642282a2020-06-23 12:00:33 -07001449 /*
1450 Breaks ending arrays/maps are always processed at the end of this
1451 function. They should never show up here.
1452 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301453 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001454 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301455 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301456 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001457
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458 /*
1459 Record the nesting level for this data item before processing any
1460 of decrementing and descending.
1461 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001462 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001463
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001465 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001467 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001468 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001469
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001470 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001471 of in the next chunk of code.
1472
1473 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001474 encloses them so a decrement needs to be done for them too, but
1475 that is done only when all the items in them have been
1476 processed, not when they are opened with the exception of an
1477 empty map or array.
1478 */
1479 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1480 pDecodedItem->uDataType,
1481 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001482 if(uReturn != QCBOR_SUCCESS) {
1483 goto Done;
1484 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001485 }
1486
Laurence Lundblade02625d42020-06-25 14:41:41 -07001487 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1488 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1489 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001490 /*
1491 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001492 - A non-aggregate like an integer or string
1493 - An empty definite length map or array
1494 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001496 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001497 definite length map/array and break detection for an indefinite
1498 length map/array. If the end of the map/array was reached, then
1499 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001500 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001501 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001502 if(uReturn) {
1503 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001504 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301505 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001506
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001507 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001508 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001509 Tell the caller what level is next. This tells them what
1510 maps/arrays were closed out and makes it possible for them to
1511 reconstruct the tree with just the information returned in
1512 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001513 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001514 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001515 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001516 pDecodedItem->uNextNestLevel = 0;
1517 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001518 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001519 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001520
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001521Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001522 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001523 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001524 memset(pDecodedItem, 0, sizeof(QCBORItem));
1525 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001526 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001527}
1528
1529
Laurence Lundblade59289e52019-12-30 13:44:37 -08001530/*
1531 Mostly just assign the right data type for the date string.
1532 */
1533inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1534{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001535 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1536 return QCBOR_ERR_BAD_OPT_TAG;
1537 }
1538
1539 const UsefulBufC Temp = pDecodedItem->val.string;
1540 pDecodedItem->val.dateString = Temp;
1541 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1542 return QCBOR_SUCCESS;
1543}
1544
1545
1546/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001547 The epoch formatted date. Turns lots of different forms of encoding
1548 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001549 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001550static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001551{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001552 QCBORError nReturn = QCBOR_SUCCESS;
1553
1554 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1555
1556 switch (pDecodedItem->uDataType) {
1557
1558 case QCBOR_TYPE_INT64:
1559 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1560 break;
1561
1562 case QCBOR_TYPE_UINT64:
1563 if(pDecodedItem->val.uint64 > INT64_MAX) {
1564 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1565 goto Done;
1566 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001567 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001568 break;
1569
1570 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001571 case QCBOR_TYPE_FLOAT:
1572#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001573 {
1574 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001575 // conversion to an int64_t to be able to detect doubles that
1576 // are too large to fit into an int64_t. A double has 52
1577 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1578 // to a double actually causes a round up which is bad and
1579 // wrong for the comparison because it will allow conversion
1580 // of doubles that can't fit into a uint64_t. To remedy this
1581 // INT64_MAX - 0x7ff is used as the cutoff point because if
1582 // that value rounds up in conversion to double it will still
1583 // be less than INT64_MAX. 0x7ff is picked because it has 11
1584 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001585 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001586 // INT64_MAX seconds is on the order of 10 billion years, and
1587 // the earth is less than 5 billion years old, so for most
1588 // uses this conversion error won't occur even though doubles
1589 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001590 //
1591 // Without the 0x7ff there is a ~30 minute range of time
1592 // values 10 billion years in the past and in the future
Laurence Lundblade9682a532020-06-06 18:33:04 -07001593 // where this this code would go wrong and some compilers
1594 // will generate warnings or errors.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001595 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1596 pDecodedItem->val.dfnum :
1597 (double)pDecodedItem->val.fnum;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001598 if(d > (double)(INT64_MAX - 0x7ff)) {
1599 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1600 goto Done;
1601 }
1602 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001603 pDecodedItem->val.epochDate.fSecondsFraction =
1604 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001605 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001606#else
1607 /* Disabling float support causes a floating point
1608 data to error in the default below. The above code
1609 requires floating point conversion to integers and
1610 comparison which requires either floating point HW
1611 or a SW library. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001612 nReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -07001613#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001614 break;
1615
Laurence Lundblade9682a532020-06-06 18:33:04 -07001616
Laurence Lundblade59289e52019-12-30 13:44:37 -08001617 default:
1618 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1619 goto Done;
1620 }
1621 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1622
1623Done:
1624 return nReturn;
1625}
1626
1627
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001628/*
1629 Mostly just assign the right data type for the bignum.
1630 */
1631inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1632{
1633 // Stack Use: UsefulBuf 1 -- 16
1634 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1635 return QCBOR_ERR_BAD_OPT_TAG;
1636 }
1637 const UsefulBufC Temp = pDecodedItem->val.string;
1638 pDecodedItem->val.bigNum = Temp;
1639 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1640 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1641 : QCBOR_TYPE_NEGBIGNUM);
1642 return QCBOR_SUCCESS;
1643}
1644
1645
Laurence Lundblade59289e52019-12-30 13:44:37 -08001646#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1647/*
1648 Decode decimal fractions and big floats.
1649
1650 When called pDecodedItem must be the array that is tagged as a big
1651 float or decimal fraction, the array that has the two members, the
1652 exponent and mantissa.
1653
1654 This will fetch and decode the exponent and mantissa and put the
1655 result back into pDecodedItem.
1656 */
1657inline static QCBORError
1658QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1659{
1660 QCBORError nReturn;
1661
1662 // --- Make sure it is an array; track nesting level of members ---
1663 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1664 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1665 goto Done;
1666 }
1667
1668 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001669 // definite length arrays, but not for indefnite. Instead remember
1670 // the nesting level the two integers must be at, which is one
1671 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001672 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1673
1674 // --- Is it a decimal fraction or a bigfloat? ---
1675 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1676 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1677
1678 // --- Get the exponent ---
1679 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001680 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001681 if(nReturn != QCBOR_SUCCESS) {
1682 goto Done;
1683 }
1684 if(exponentItem.uNestingLevel != nNestLevel) {
1685 // Array is empty or a map/array encountered when expecting an int
1686 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1687 goto Done;
1688 }
1689 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1690 // Data arriving as an unsigned int < INT64_MAX has been converted
1691 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1692 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1693 // will be too large for this to handle and thus an error that will
1694 // get handled in the next else.
1695 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1696 } else {
1697 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1698 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1699 goto Done;
1700 }
1701
1702 // --- Get the mantissa ---
1703 QCBORItem mantissaItem;
1704 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1705 if(nReturn != QCBOR_SUCCESS) {
1706 goto Done;
1707 }
1708 if(mantissaItem.uNestingLevel != nNestLevel) {
1709 // Mantissa missing or map/array encountered when expecting number
1710 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1711 goto Done;
1712 }
1713 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1714 // Data arriving as an unsigned int < INT64_MAX has been converted
1715 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1716 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1717 // will be too large for this to handle and thus an error that
1718 // will get handled in an else below.
1719 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1720 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1721 // Got a good big num mantissa
1722 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1723 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001724 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1725 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1726 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001727 } else {
1728 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1729 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1730 goto Done;
1731 }
1732
1733 // --- Check that array only has the two numbers ---
1734 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001735 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001736 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1737 goto Done;
1738 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001739 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001740
1741Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001742 return nReturn;
1743}
1744#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1745
1746
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001747inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1748{
1749 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1750 return QCBOR_ERR_BAD_OPT_TAG;
1751 }
1752 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1753 return QCBOR_SUCCESS;
1754}
1755
1756
1757inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1758{
1759 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1760 return QCBOR_ERR_BAD_OPT_TAG;
1761 }
1762 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1763 return QCBOR_SUCCESS;
1764}
1765
1766
1767inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1768{
1769 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1770 return QCBOR_ERR_BAD_OPT_TAG;
1771 }
1772 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1773 return QCBOR_SUCCESS;
1774}
1775
1776
1777inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1778{
1779 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1780 return QCBOR_ERR_BAD_OPT_TAG;
1781 }
1782 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1783 return QCBOR_SUCCESS;
1784}
1785
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001786
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001787inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1788{
1789 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1790 return QCBOR_ERR_BAD_OPT_TAG;
1791 }
1792 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1793 return QCBOR_SUCCESS;
1794}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001795
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001796
1797inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1798{
1799 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1800 return QCBOR_ERR_BAD_OPT_TAG;
1801 }
1802 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1803 return QCBOR_SUCCESS;
1804}
1805
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001806
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001807inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1808{
1809 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1810 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001811 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001812 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1813 } else {
1814 return QCBOR_ERR_BAD_OPT_TAG;
1815 }
1816 return QCBOR_SUCCESS;
1817}
1818
1819
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001820inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1821{
1822 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1823 return QCBOR_ERR_BAD_OPT_TAG;
1824 }
1825 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1826 return QCBOR_SUCCESS;
1827}
1828
1829
Laurence Lundblade59289e52019-12-30 13:44:37 -08001830/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001831 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001832 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001833QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001834QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835{
1836 QCBORError nReturn;
1837
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001838 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001839 if(nReturn != QCBOR_SUCCESS) {
1840 goto Done;
1841 }
1842
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001843 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1844 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001845
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001846 // Many of the functions here only just map a CBOR tag to
1847 // a QCBOR_TYPE for a string and could probably be
1848 // implemented with less object code. This implementation
1849 // of string types takes about 120 bytes of object code
1850 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001851 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001852 nReturn = DecodeDateString(pDecodedItem);
1853 break;
1854
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001855 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001856 nReturn = DecodeDateEpoch(pDecodedItem);
1857 break;
1858
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001859 case CBOR_TAG_POS_BIGNUM:
1860 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001861 nReturn = DecodeBigNum(pDecodedItem);
1862 break;
1863
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001864 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1865 case CBOR_TAG_DECIMAL_FRACTION:
1866 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001867 // For aggregate tagged types, what goes into pTags is only collected
1868 // from the surrounding data item, not the contents, so pTags is not
1869 // passed on here.
1870
1871 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1872 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001873 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001874
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001875 case CBOR_TAG_CBOR:
1876 nReturn = DecodeWrappedCBOR(pDecodedItem);
1877 break;
1878
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001879 case CBOR_TAG_CBOR_SEQUENCE:
1880 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1881 break;
1882
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001883 case CBOR_TAG_URI:
1884 nReturn = DecodeURI(pDecodedItem);
1885 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001886
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001887 case CBOR_TAG_B64URL:
1888 nReturn = DecodeB64URL(pDecodedItem);
1889 break;
1890
1891 case CBOR_TAG_B64:
1892 nReturn = DecodeB64(pDecodedItem);
1893 break;
1894
1895 case CBOR_TAG_MIME:
1896 case CBOR_TAG_BINARY_MIME:
1897 nReturn = DecodeMIME(pDecodedItem);
1898 break;
1899
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001900 case CBOR_TAG_REGEX:
1901 nReturn = DecodeRegex(pDecodedItem);
1902 break;
1903
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001904 case CBOR_TAG_BIN_UUID:
1905 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001906 break;
1907
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001908 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001909 // The end of the tag list or no tags
1910 // Successful exit from the loop.
1911 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001912
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001913 default:
1914 // A tag that is not understood
1915 // A successful exit from the loop
1916 goto Done;
1917
1918 }
1919 if(nReturn != QCBOR_SUCCESS) {
1920 goto Done;
1921 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922 }
1923
1924Done:
1925 if(nReturn != QCBOR_SUCCESS) {
1926 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1927 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1928 }
1929 return nReturn;
1930}
1931
1932
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001933QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1934{
1935 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1936
1937 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1938
1939 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07001940 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001941
1942 return uErr;
1943}
1944
1945
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001947 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001948 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001949QCBORError
1950QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1951 QCBORItem *pDecodedItem,
1952 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001953{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001954 QCBORError nReturn;
1955
1956 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1957 if(nReturn != QCBOR_SUCCESS) {
1958 return nReturn;
1959 }
1960
1961 if(pTags != NULL) {
1962 pTags->uNumUsed = 0;
1963 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001964 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001965 break;
1966 }
1967 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1968 return QCBOR_ERR_TOO_MANY_TAGS;
1969 }
1970 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1971 pTags->uNumUsed++;
1972 }
1973 }
1974
1975 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001976}
1977
1978
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001979/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301980 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301981 next one down. If a layer has no work to do for a particular item
1982 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001983
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1985 tagged data items, turning them into the local C representation.
1986 For the most simple it is just associating a QCBOR_TYPE with the data. For
1987 the complex ones that an aggregate of data items, there is some further
1988 decoding and a little bit of recursion.
1989
1990 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301991 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301992 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001993 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001994
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301995 - GetNext_MapEntry -- This handles the combining of two
1996 items, the label and the data, that make up a map entry.
1997 It only does work on maps. It combines the label and data
1998 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001999
Laurence Lundblade59289e52019-12-30 13:44:37 -08002000 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2001 tags into bit flags associated with the data item. No actual decoding
2002 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002003
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302005 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302006 string allocater to create contiguous space for the item. It
2007 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002008
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2010 atomic data item has a "major type", an integer "argument" and optionally
2011 some content. For text and byte strings, the content is the bytes
2012 that make up the string. These are the smallest data items that are
2013 considered to be well-formed. The content may also be other data items in
2014 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002015
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002016 Roughly this takes 300 bytes of stack for vars. Need to
2017 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302019 */
2020
2021
2022/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002023 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002024 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002025bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002026 const QCBORItem *pItem,
2027 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002028{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002029 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002030 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002031 break;
2032 }
2033 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002034 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002035 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002037
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002038 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002039}
2040
2041
2042/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002043 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002044 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002045QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002046{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002047 QCBORError uReturn = me->uLastError;
2048
2049 if(uReturn != QCBOR_SUCCESS) {
2050 goto Done;
2051 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002052
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002053 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002054 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002055 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002056 goto Done;
2057 }
2058
2059 // Error out if not all the bytes are consumed
2060 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002061 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002063
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002064Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302065 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002066 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002067 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002068
Laurence Lundblade085d7952020-07-24 10:26:30 -07002069 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002070}
2071
2072
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002073/*
2074Public function, see header qcbor/qcbor_decode.h file
2075*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002076uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2077 const QCBORItem *pItem,
2078 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002079{
2080 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2081 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002082 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002083 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002084 }
2085}
2086
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002087
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002088/*
2089
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002090Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002091
Laurence Lundbladeee851742020-01-08 08:37:05 -08002092 - Hit end of input before it was expected while decoding type and
2093 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002094
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002095 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002096
Laurence Lundbladeee851742020-01-08 08:37:05 -08002097 - Hit end of input while decoding a text or byte string
2098 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002099
Laurence Lundbladeee851742020-01-08 08:37:05 -08002100 - Encountered conflicting tags -- e.g., an item is tagged both a date
2101 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002102
Laurence Lundbladeee851742020-01-08 08:37:05 -08002103 - Encontered an array or mapp that has too many items
2104 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002105
Laurence Lundbladeee851742020-01-08 08:37:05 -08002106 - Encountered array/map nesting that is too deep
2107 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002108
Laurence Lundbladeee851742020-01-08 08:37:05 -08002109 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2110 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002111
Laurence Lundbladeee851742020-01-08 08:37:05 -08002112 - The type of a map label is not a string or int
2113 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002115 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002116
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002117 */
2118
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002119
2120
Laurence Lundbladef6531662018-12-04 10:42:22 +09002121
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002122/* ===========================================================================
2123 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002124
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002125 This implements a simple sting allocator for indefinite length
2126 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2127 implements the function type QCBORStringAllocate and allows easy
2128 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002129
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002130 This particular allocator is built-in for convenience. The caller
2131 can implement their own. All of this following code will get
2132 dead-stripped if QCBORDecode_SetMemPool() is not called.
2133
2134 This is a very primitive memory allocator. It does not track
2135 individual allocations, only a high-water mark. A free or
2136 reallocation must be of the last chunk allocated.
2137
2138 The size of the pool and offset to free memory are packed into the
2139 first 8 bytes of the memory pool so we don't have to keep them in
2140 the decode context. Since the address of the pool may not be
2141 aligned, they have to be packed and unpacked as if they were
2142 serialized data of the wire or such.
2143
2144 The sizes packed in are uint32_t to be the same on all CPU types
2145 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002146 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002147
2148
Laurence Lundbladeee851742020-01-08 08:37:05 -08002149static inline int
2150MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002151{
2152 // Use of UsefulInputBuf is overkill, but it is convenient.
2153 UsefulInputBuf UIB;
2154
Laurence Lundbladeee851742020-01-08 08:37:05 -08002155 // Just assume the size here. It was checked during SetUp so
2156 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002157 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2158 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2159 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2160 return UsefulInputBuf_GetError(&UIB);
2161}
2162
2163
Laurence Lundbladeee851742020-01-08 08:37:05 -08002164static inline int
2165MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002166{
2167 // Use of UsefulOutBuf is overkill, but convenient. The
2168 // length check performed here is useful.
2169 UsefulOutBuf UOB;
2170
2171 UsefulOutBuf_Init(&UOB, Pool);
2172 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2173 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2174 return UsefulOutBuf_GetError(&UOB);
2175}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002176
2177
2178/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002179 Internal function for an allocation, reallocation free and destuct.
2180
2181 Having only one function rather than one each per mode saves space in
2182 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002183
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002184 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2185 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002186static UsefulBuf
2187MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002188{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002189 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002190
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002191 uint32_t uPoolSize;
2192 uint32_t uFreeOffset;
2193
2194 if(uNewSize > UINT32_MAX) {
2195 // This allocator is only good up to 4GB. This check should
2196 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2197 goto Done;
2198 }
2199 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2200
2201 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2202 goto Done;
2203 }
2204
2205 if(uNewSize) {
2206 if(pMem) {
2207 // REALLOCATION MODE
2208 // Calculate pointer to the end of the memory pool. It is
2209 // assumed that pPool + uPoolSize won't wrap around by
2210 // assuming the caller won't pass a pool buffer in that is
2211 // not in legitimate memory space.
2212 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2213
2214 // Check that the pointer for reallocation is in the range of the
2215 // pool. This also makes sure that pointer math further down
2216 // doesn't wrap under or over.
2217 if(pMem >= pPool && pMem < pPoolEnd) {
2218 // Offset to start of chunk for reallocation. This won't
2219 // wrap under because of check that pMem >= pPool. Cast
2220 // is safe because the pool is always less than UINT32_MAX
2221 // because of check in QCBORDecode_SetMemPool().
2222 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2223
2224 // Check to see if the allocation will fit. uPoolSize -
2225 // uMemOffset will not wrap under because of check that
2226 // pMem is in the range of the uPoolSize by check above.
2227 if(uNewSize <= uPoolSize - uMemOffset) {
2228 ReturnValue.ptr = pMem;
2229 ReturnValue.len = uNewSize;
2230
2231 // Addition won't wrap around over because uNewSize was
2232 // checked to be sure it is less than the pool size.
2233 uFreeOffset = uMemOffset + uNewSize32;
2234 }
2235 }
2236 } else {
2237 // ALLOCATION MODE
2238 // uPoolSize - uFreeOffset will not underflow because this
2239 // pool implementation makes sure uFreeOffset is always
2240 // smaller than uPoolSize through this check here and
2241 // reallocation case.
2242 if(uNewSize <= uPoolSize - uFreeOffset) {
2243 ReturnValue.len = uNewSize;
2244 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002245 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002246 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002247 }
2248 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002249 if(pMem) {
2250 // FREE MODE
2251 // Cast is safe because of limit on pool size in
2252 // QCBORDecode_SetMemPool()
2253 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2254 } else {
2255 // DESTRUCT MODE
2256 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002257 }
2258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002259
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002260 UsefulBuf Pool = {pPool, uPoolSize};
2261 MemPool_Pack(Pool, uFreeOffset);
2262
2263Done:
2264 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002265}
2266
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002267
Laurence Lundbladef6531662018-12-04 10:42:22 +09002268/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002269 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002270 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002271QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2272 UsefulBuf Pool,
2273 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002274{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002275 // The pool size and free mem offset are packed into the beginning
2276 // of the pool memory. This compile time check make sure the
2277 // constant in the header is correct. This check should optimize
2278 // down to nothing.
2279 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002280 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002281 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002282
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002283 // The pool size and free offset packed in to the beginning of pool
2284 // memory are only 32-bits. This check will optimize out on 32-bit
2285 // machines.
2286 if(Pool.len > UINT32_MAX) {
2287 return QCBOR_ERR_BUFFER_TOO_LARGE;
2288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002289
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002290 // This checks that the pool buffer given is big enough.
2291 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2292 return QCBOR_ERR_BUFFER_TOO_SMALL;
2293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002295 pMe->StringAllocator.pfAllocator = MemPool_Function;
2296 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2297 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002298
Laurence Lundblade30816f22018-11-10 13:40:22 +07002299 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002300}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002302
2303
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002304
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002305
2306
2307/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002308 Consume an entire map or array (and do next to
2309 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002310 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002311static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002312ConsumeItem(QCBORDecodeContext *pMe,
2313 const QCBORItem *pItemToConsume,
2314 uint_fast8_t *puNextNestLevel)
2315{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002316 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002317 QCBORItem Item;
2318
Laurence Lundblade02625d42020-06-25 14:41:41 -07002319 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002320
Laurence Lundblade02625d42020-06-25 14:41:41 -07002321 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002322 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002323
Laurence Lundblade1341c592020-04-11 14:19:05 -07002324 /* This works for definite and indefinite length
2325 * maps and arrays by using the nesting level
2326 */
2327 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002328 uReturn = QCBORDecode_GetNext(pMe, &Item);
2329 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002330 goto Done;
2331 }
2332 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002333
Laurence Lundblade1341c592020-04-11 14:19:05 -07002334 if(puNextNestLevel != NULL) {
2335 *puNextNestLevel = Item.uNextNestLevel;
2336 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002337 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002338
Laurence Lundblade1341c592020-04-11 14:19:05 -07002339 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002340 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002341 if(puNextNestLevel != NULL) {
2342 /* Just pass the nesting level through */
2343 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2344 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002345 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002346 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002347
2348Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002349 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002350}
2351
2352
Laurence Lundblade1341c592020-04-11 14:19:05 -07002353/* Return true if the labels in Item1 and Item2 are the same.
2354 Works only for integer and string labels. Returns false
2355 for any other type. */
2356static inline bool
2357MatchLabel(QCBORItem Item1, QCBORItem Item2)
2358{
2359 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2360 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2361 return true;
2362 }
2363 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002364 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002365 return true;
2366 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002367 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002368 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2369 return true;
2370 }
2371 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2372 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2373 return true;
2374 }
2375 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002376
Laurence Lundblade1341c592020-04-11 14:19:05 -07002377 /* Other label types are never matched */
2378 return false;
2379}
2380
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002381
2382/*
2383 Returns true if Item1 and Item2 are the same type
2384 or if either are of QCBOR_TYPE_ANY.
2385 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002386static inline bool
2387MatchType(QCBORItem Item1, QCBORItem Item2)
2388{
2389 if(Item1.uDataType == Item2.uDataType) {
2390 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002391 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002392 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002393 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002394 return true;
2395 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002396 return false;
2397}
2398
2399
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002400/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002401 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002402
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002403 @param[in] pMe The decode context to search.
2404 @param[in,out] pItemArray The items to search for and the items found.
2405 @param[out] puOffset Byte offset of last item matched.
2406 @param[in] pCBContext Context for the not-found item call back.
2407 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002408
2409 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2410
2411 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found for one of the labels being search for. This duplicate detection is only performed for items in pItemArray, not every item in the map.
2412
2413 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2414
2415 @retval Also errors returned by QCBORDecode_GetNext().
2416
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002417 On input pItemArray contains a list of labels and data types
2418 of items to be found.
2419
2420 On output the fully retrieved items are filled in with
2421 values and such. The label was matched, so it never changes.
2422
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002423 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002424 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002425static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002426MapSearch(QCBORDecodeContext *pMe,
2427 QCBORItem *pItemArray,
2428 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002429 void *pCBContext,
2430 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002431{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002432 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002433 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002434
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002435 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002436 uReturn = pMe->uLastError;
2437 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002438 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002439
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002440 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002441 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2442 /* QCBOR_TYPE_NONE as first item indicates just looking
2443 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002444 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2445 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002446 }
2447
Laurence Lundblade085d7952020-07-24 10:26:30 -07002448 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2449 // It is an empty bounded array or map
2450 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2451 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002452 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002453 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002454 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002455 // Nothing is ever found in an empty array or map. All items
2456 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002457 uReturn = QCBOR_SUCCESS;
2458 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002459 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002460 }
2461
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002462 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002463 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2464
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002465 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002466 UsefulInputBuf_Seek(&(pMe->InBuf),
2467 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002468
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002469 /*
2470 Loop over all the items in the map. They could be
2471 deeply nested and this should handle both definite
2472 and indefinite length maps and arrays, so this
2473 adds some complexity.
2474 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002475 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002476 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002477 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002478 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002481 /* Get the item */
2482 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002483 uReturn = QCBORDecode_GetNext(pMe, &Item);
2484 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002485 /* Got non-well-formed CBOR */
2486 goto Done;
2487 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002488
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002489 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002490 bool bMatched = false;
2491 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2492 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002493 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002494 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2495 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002496 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002497 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002498 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002499 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002500 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002501 goto Done;
2502 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002503
Laurence Lundblade1341c592020-04-11 14:19:05 -07002504 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002505 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002506 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002508 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002510 bMatched = true;
2511 }
2512 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002513
2514
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002515 if(!bMatched && pfCallback != NULL) {
2516 /*
2517 Call the callback on unmatched labels.
2518 (It is tempting to do duplicate detection here, but that would
2519 require dynamic memory allocation because the number of labels
2520 that might be encountered is unbounded.)
2521 */
2522 uReturn = (*pfCallback)(pCBContext, &Item);
2523 if(uReturn != QCBOR_SUCCESS) {
2524 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002525 }
2526 }
2527
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002528 /*
2529 Consume the item whether matched or not. This
2530 does the work of traversing maps and array and
2531 everything in them. In this loop only the
2532 items at the current nesting level are examined
2533 to match the labels.
2534 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002535 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2536 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002537 goto Done;
2538 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002539
2540 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002541
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002542 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002543
2544 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002545 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2546 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002547
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002548 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002549 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2550
2551 Done2:
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002552 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2553 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002554 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002555 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002556 }
2557 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002558
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002559 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560}
2561
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002562
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002563/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002564 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002565*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002566void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2567 int64_t nLabel,
2568 uint8_t uQcborType,
2569 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002570{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002571 if(pMe->uLastError != QCBOR_SUCCESS) {
2572 return;
2573 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002574
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002575 QCBORItem OneItemSeach[2];
2576 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2577 OneItemSeach[0].label.int64 = nLabel;
2578 OneItemSeach[0].uDataType = uQcborType;
2579 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002580
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002581 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2582 if(uReturn != QCBOR_SUCCESS) {
2583 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002584 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002585 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002586 uReturn = QCBOR_ERR_NOT_FOUND;
2587 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002588 }
2589
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002590 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002591
2592 Done:
2593 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002594}
2595
2596
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002597/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002598 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002599*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002600void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2601 const char *szLabel,
2602 uint8_t uQcborType,
2603 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002604{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002605 if(pMe->uLastError != QCBOR_SUCCESS) {
2606 return;
2607 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002608
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002609 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002610 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2611 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2612 OneItemSeach[0].uDataType = uQcborType;
2613 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002614
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002615 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2616 if(uReturn != QCBOR_SUCCESS) {
2617 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002618 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002619 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002620 uReturn = QCBOR_ERR_NOT_FOUND;
2621 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002622 }
2623
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002624 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002625
2626Done:
2627 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002628}
2629
2630
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002631
2632static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2633{
2634 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2635 if(uDataType == puTypeList[i]) {
2636 return QCBOR_SUCCESS;
2637 }
2638 }
2639 return QCBOR_ERR_UNEXPECTED_TYPE;
2640}
2641
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002642
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002643/**
2644 @param[in] TagSpec Specification for matching tags.
2645 @param[in] uDataType A QCBOR data type
2646
2647 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2648 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2649
2650 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2651 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002652static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002653{
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002654 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002655 // Must match the tag and only the tag
2656 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002657 }
2658
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002659 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2660 if(uReturn == QCBOR_SUCCESS) {
2661 return QCBOR_SUCCESS;
2662 }
2663
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002664 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002665 /* Must match the content type and only the content type.
2666 There was no match just above so it is a fail. */
2667 return QCBOR_ERR_UNEXPECTED_TYPE;
2668 }
2669
2670 /* If here it can match either the tag or the content
2671 and it hasn't matched the content, so the end
2672 result is whether it matches the tag. This is
2673 also the case that the CBOR standard discourages. */
2674
2675 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002676}
2677
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002678
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002679// Semi-private
2680// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002681void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2682 int64_t nLabel,
2683 TagSpecification TagSpec,
2684 QCBORItem *pItem)
2685{
2686 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2687 if(pMe->uLastError != QCBOR_SUCCESS) {
2688 return;
2689 }
2690
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002691 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002692}
2693
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002694// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002695void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2696 const char *szLabel,
2697 TagSpecification TagSpec,
2698 QCBORItem *pItem)
2699{
2700 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2701 if(pMe->uLastError != QCBOR_SUCCESS) {
2702 return;
2703 }
2704
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002705 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002706}
2707
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002708// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002709void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2710 int64_t nLabel,
2711 TagSpecification TagSpec,
2712 UsefulBufC *pString)
2713{
2714 QCBORItem Item;
2715 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2716 if(pMe->uLastError == QCBOR_SUCCESS) {
2717 *pString = Item.val.string;
2718 }
2719}
2720
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002721// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002722void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2723 const char * szLabel,
2724 TagSpecification TagSpec,
2725 UsefulBufC *pString)
2726{
2727 QCBORItem Item;
2728 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2729 if(pMe->uLastError == QCBOR_SUCCESS) {
2730 *pString = Item.val.string;
2731 }
2732}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002733
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002734/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002735 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002736*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002737QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2738{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002739 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002740}
2741
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002742/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002743 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002744*/
2745QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2746 QCBORItem *pItemList,
2747 void *pCallbackCtx,
2748 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002749{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002750 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002751}
2752
2753
Laurence Lundblade34691b92020-05-18 22:25:25 -07002754static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002756 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002757 if(pMe->uLastError != QCBOR_SUCCESS) {
2758 // Already in error state; do nothing.
2759 return;
2760 }
2761
2762 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002763 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002764 if(pMe->uLastError != QCBOR_SUCCESS) {
2765 return;
2766 }
2767
Laurence Lundblade085d7952020-07-24 10:26:30 -07002768 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2769 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2770 return;
2771 }
2772
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002773 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002774 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002775
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002776 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002777 be at the right place.
2778
2779 The UsefulInBuf offset could be anywhere, so no assumption is
2780 made about it.
2781
2782 No assumption is made about the pre-order nesting level either.
2783
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002784 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002785 the map level that is being entered.
2786 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002787 /* Seek to the data item that is the map or array */
2788 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002789
2790 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002791
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002792 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002793}
2794
2795
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002796/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002797 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002798*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002799void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002800{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002801 QCBORItem OneItemSeach[2];
2802 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2803 OneItemSeach[0].label.int64 = nLabel;
2804 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2805 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002806
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002807 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002808 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809}
2810
2811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002814*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002815void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002816{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002817 QCBORItem OneItemSeach[2];
2818 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2819 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2820 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2821 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002822
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002823 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002824}
2825
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002826/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002827 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002828*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002829void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002830{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002831 QCBORItem OneItemSeach[2];
2832 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2833 OneItemSeach[0].label.int64 = nLabel;
2834 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2835 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002836
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002837 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002838}
2839
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002840/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002841 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002842*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002843void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2844{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002845 QCBORItem OneItemSeach[2];
2846 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2847 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2848 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2849 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002850
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002851 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002852}
2853
2854
Laurence Lundblade02625d42020-06-25 14:41:41 -07002855// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002856void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002857{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002858 QCBORError uErr;
2859
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002860 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002861 if(pMe->uLastError != QCBOR_SUCCESS) {
2862 // Already in error state; do nothing.
2863 return;
2864 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002865
2866 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002867 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002868 uErr = QCBORDecode_GetNext(pMe, &Item);
2869 if(uErr != QCBOR_SUCCESS) {
2870 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002871 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002872 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002873 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2874 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002875 }
2876
Laurence Lundbladef0499502020-08-01 11:55:57 -07002877 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002878 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002879 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2880 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002881 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002882 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2883 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002884 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2885 DecodeNesting_Descend(&(pMe->nesting), uType);
2886 }
2887
Laurence Lundblade02625d42020-06-25 14:41:41 -07002888 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002889
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002890 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2891 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002892
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002893Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002894 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002895}
2896
Laurence Lundblade02625d42020-06-25 14:41:41 -07002897
2898/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002899 This is the common work for exiting a level that is a bounded map, array or bstr
2900 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002901
2902 One chunk of work is to set up the pre-order traversal so it is at
2903 the item just after the bounded map, array or bstr that is being
2904 exited. This is somewhat complex.
2905
2906 The other work is to level-up the bounded mode to next higest bounded
2907 mode or the top level if there isn't one.
2908 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002909static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002910ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002911{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002912 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002913
Laurence Lundblade02625d42020-06-25 14:41:41 -07002914 /*
2915 First the pre-order-traversal byte offset is positioned to the
2916 item just after the bounded mode item that was just consumed.
2917 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002918 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2919
Laurence Lundblade02625d42020-06-25 14:41:41 -07002920 /*
2921 Next, set the current nesting level to one above the bounded level
2922 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002923
Laurence Lundblade02625d42020-06-25 14:41:41 -07002924 DecodeNesting_CheckBoundedType() is always called before this and
2925 makes sure pCurrentBounded is valid.
2926 */
2927 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2928
2929 /*
2930 This does the complex work of leveling up the pre-order traversal
2931 when the end of a map or array or another bounded level is
2932 reached. It may do nothing, or ascend all the way to the top
2933 level.
2934 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002935 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002936 if(uErr != QCBOR_SUCCESS) {
2937 goto Done;
2938 }
2939
Laurence Lundblade02625d42020-06-25 14:41:41 -07002940 /*
2941 This makes the next highest bounded level the current bounded
2942 level. If there is no next highest level, then no bounded mode is
2943 in effect.
2944 */
2945 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002946
Laurence Lundblade02625d42020-06-25 14:41:41 -07002947 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002948
2949Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002950 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002951 return uErr;
2952}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002953
Laurence Lundblade02625d42020-06-25 14:41:41 -07002954
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002955// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002956void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002957{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002958 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002959 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002960 return;
2961 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002962
Laurence Lundblade02625d42020-06-25 14:41:41 -07002963 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002964
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002965 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002966 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2967 goto Done;
2968 }
2969
Laurence Lundblade02625d42020-06-25 14:41:41 -07002970 /*
2971 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002972 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002973 from previous map search, then do a dummy search.
2974 */
2975 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002976 QCBORItem Dummy;
2977 Dummy.uLabelType = QCBOR_TYPE_NONE;
2978 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2979 if(uErr != QCBOR_SUCCESS) {
2980 goto Done;
2981 }
2982 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002983
Laurence Lundblade02625d42020-06-25 14:41:41 -07002984 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002985
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002986Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002987 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002988}
2989
2990
Laurence Lundblade1341c592020-04-11 14:19:05 -07002991
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002992static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002993 const QCBORItem *pItem,
2994 uint8_t uTagRequirement,
2995 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002996{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002997 if(pBstr) {
2998 *pBstr = NULLUsefulBufC;
2999 }
3000
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003001 if(pMe->uLastError != QCBOR_SUCCESS) {
3002 // Already in error state; do nothing.
3003 return pMe->uLastError;
3004 }
3005
3006 QCBORError uError = QCBOR_SUCCESS;
3007
3008 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3009 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3010 goto Done;;
3011 }
3012
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003013 const TagSpecification TagSpec =
3014 {
3015 uTagRequirement,
3016 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3017 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3018 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003019
3020 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
3021 if(uError != QCBOR_SUCCESS) {
3022 goto Done;
3023 }
3024
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003025 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003026 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003027 so the increment in NestLevelAscender called by ExitBoundedLevel()
3028 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003029 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003030 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003031
3032 if(pBstr) {
3033 *pBstr = pItem->val.string;
3034 }
3035
3036 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003037
3038 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003039 // Most of these calls are simple inline accessors so this doesn't
3040 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003041 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003042 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3043 // TODO: test this error condition
3044 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
3045 goto Done;
3046 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003047 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003048 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003049
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003050 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003051 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003052 (uint32_t)uPreviousLength,
3053 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003054Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003055 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003056
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003057 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003058}
3059
3060
Laurence Lundblade02625d42020-06-25 14:41:41 -07003061/*
3062 Public function, see header qcbor/qcbor_decode.h file
3063 */
3064void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003065 uint8_t uTagRequirement,
3066 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003067{
3068 if(pMe->uLastError != QCBOR_SUCCESS) {
3069 // Already in error state; do nothing.
3070 return;
3071 }
3072
3073 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003074 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003075 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3076 if(pMe->uLastError != QCBOR_SUCCESS) {
3077 return;
3078 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003079
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003080 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003081 &Item,
3082 uTagRequirement,
3083 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003084}
3085
3086
Laurence Lundblade02625d42020-06-25 14:41:41 -07003087/*
3088 Public function, see header qcbor/qcbor_decode.h file
3089 */
3090void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003091 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003092 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003093 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003094{
3095 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003096 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003097
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003098 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003099}
3100
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003101
Laurence Lundblade02625d42020-06-25 14:41:41 -07003102/*
3103 Public function, see header qcbor/qcbor_decode.h file
3104 */
3105void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003106 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003107 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003108 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003109{
3110 QCBORItem Item;
3111 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3112
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003113 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003114}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003115
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003116
Laurence Lundblade02625d42020-06-25 14:41:41 -07003117/*
3118 Public function, see header qcbor/qcbor_decode.h file
3119 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003120void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003121{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 if(pMe->uLastError != QCBOR_SUCCESS) {
3123 // Already in error state; do nothing.
3124 return;
3125 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003126
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003127 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003128 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3129 return;
3130 }
3131
3132 /*
3133 Reset the length of the UsefulInputBuf to what it was before
3134 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003135 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003136 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3137 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003138
3139
Laurence Lundblade02625d42020-06-25 14:41:41 -07003140 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003141 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003142}
3143
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003144
Laurence Lundbladee6430642020-03-14 21:15:44 -07003145
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003146
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003147
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003148
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003149
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003150
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003151static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3152{
3153 switch(pItem->uDataType) {
3154 case QCBOR_TYPE_TRUE:
3155 *pBool = true;
3156 return QCBOR_SUCCESS;
3157 break;
3158
3159 case QCBOR_TYPE_FALSE:
3160 *pBool = false;
3161 return QCBOR_SUCCESS;
3162 break;
3163
3164 default:
3165 return QCBOR_ERR_UNEXPECTED_TYPE;
3166 break;
3167 }
3168}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003169
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003170
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003171/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003172 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003173*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003174void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003175{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003176 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003177 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003178 return;
3179 }
3180
Laurence Lundbladec4537442020-04-14 18:53:22 -07003181 QCBORError nError;
3182 QCBORItem Item;
3183
3184 nError = QCBORDecode_GetNext(pMe, &Item);
3185 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003186 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003187 return;
3188 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003189 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003190}
3191
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003192
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003193/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003194 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003195*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003196void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003197{
3198 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003199 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003200
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003201 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003202}
3203
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003204
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003205/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003206 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003207*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003208void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3209{
3210 QCBORItem Item;
3211 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3212
3213 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3214}
3215
3216
3217
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003218void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3219 TagSpecification TagSpec,
3220 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003221{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003222 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003223 // Already in error state, do nothing
3224 return;
3225 }
3226
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003227 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003228 QCBORItem Item;
3229
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003230 uError = QCBORDecode_GetNext(pMe, &Item);
3231 if(uError != QCBOR_SUCCESS) {
3232 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003233 return;
3234 }
3235
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003236 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3237
3238 if(pMe->uLastError == QCBOR_SUCCESS) {
3239 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003240 }
3241}
3242
Laurence Lundbladec4537442020-04-14 18:53:22 -07003243
3244
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003245
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003246static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003247 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003248 UsefulBufC *pValue,
3249 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003250{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003251 const TagSpecification TagSpec =
3252 {
3253 uTagRequirement,
3254 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3255 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3256 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003257
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003258 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3259 if(uErr != QCBOR_SUCCESS) {
3260 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003261 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003262
3263 *pValue = pItem->val.string;
3264
3265 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3266 *pbIsNegative = false;
3267 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3268 *pbIsNegative = true;
3269 }
3270
3271 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003272}
3273
3274
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003275/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003276 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003277 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003278void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3279 uint8_t uTagRequirement,
3280 UsefulBufC *pValue,
3281 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003282{
3283 if(pMe->uLastError != QCBOR_SUCCESS) {
3284 // Already in error state, do nothing
3285 return;
3286 }
3287
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003288 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003289 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3290 if(uError != QCBOR_SUCCESS) {
3291 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003292 return;
3293 }
3294
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003295 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003296}
3297
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003298
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003299/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003300 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003301*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003302void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3303 int64_t nLabel,
3304 uint8_t uTagRequirement,
3305 UsefulBufC *pValue,
3306 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003307{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003308 QCBORItem Item;
3309 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003310 if(pMe->uLastError != QCBOR_SUCCESS) {
3311 return;
3312 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003313
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003314 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315}
3316
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003317
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003318/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003319 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003320*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003321void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3322 const char *szLabel,
3323 uint8_t uTagRequirement,
3324 UsefulBufC *pValue,
3325 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003326{
3327 QCBORItem Item;
3328 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003329 if(pMe->uLastError != QCBOR_SUCCESS) {
3330 return;
3331 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003332
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003333 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003334}
3335
3336
3337
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003338
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003339// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003340QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3341 const QCBORItem *pItem,
3342 UsefulBufC *pMessage,
3343 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003344{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003345 const TagSpecification TagSpecText =
3346 {
3347 uTagRequirement,
3348 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3349 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3350 };
3351 const TagSpecification TagSpecBinary =
3352 {
3353 uTagRequirement,
3354 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3355 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3356 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003357
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003358 QCBORError uReturn;
3359
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003360 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003361 *pMessage = pItem->val.string;
3362 if(pbIsNot7Bit != NULL) {
3363 *pbIsNot7Bit = false;
3364 }
3365 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003366 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003367 *pMessage = pItem->val.string;
3368 if(pbIsNot7Bit != NULL) {
3369 *pbIsNot7Bit = true;
3370 }
3371 uReturn = QCBOR_SUCCESS;
3372
3373 } else {
3374 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3375 }
3376
3377 return uReturn;
3378}
3379
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003380// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3381
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003382
3383
3384
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003385#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003387typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003388
3389
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003390// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003391static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003392{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003393 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003394
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003395 if(uResult != 0) {
3396 /* This loop will run a maximum of 19 times because
3397 * UINT64_MAX < 10 ^^ 19. More than that will cause
3398 * exit with the overflow error
3399 */
3400 for(; nExponent > 0; nExponent--) {
3401 if(uResult > UINT64_MAX / 10) {
3402 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3403 }
3404 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003405 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003406
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003407 for(; nExponent < 0; nExponent++) {
3408 uResult = uResult / 10;
3409 if(uResult == 0) {
3410 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3411 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003412 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003413 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003414 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003415
3416 *puResult = uResult;
3417
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003418 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003419}
3420
3421
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003422// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003423static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003424{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003425 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003426
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003427 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003428
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003430 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003431 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003432 */
3433 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003434 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003435 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003436 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003437 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003438 nExponent--;
3439 }
3440
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003441 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003442 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003443 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3444 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003445 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003446 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003447 }
3448
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003449 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003451 return QCBOR_SUCCESS;
3452}
3453
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003454
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003455/*
3456 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3457 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003458static inline QCBORError ExponentiateNN(int64_t nMantissa,
3459 int64_t nExponent,
3460 int64_t *pnResult,
3461 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003462{
3463 uint64_t uResult;
3464
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003465 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003466 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003467 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3468
3469 // Do the exponentiation of the positive mantissa
3470 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3471 if(uReturn) {
3472 return uReturn;
3473 }
3474
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003475
Laurence Lundblade983500d2020-05-14 11:49:34 -07003476 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3477 of INT64_MIN. This assumes two's compliment representation where
3478 INT64_MIN is one increment farther from 0 than INT64_MAX.
3479 Trying to write -INT64_MIN doesn't work to get this because the
3480 compiler tries to work with an int64_t which can't represent
3481 -INT64_MIN.
3482 */
3483 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3484
3485 // Error out if too large
3486 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003487 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3488 }
3489
3490 // Casts are safe because of checks above
3491 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3492
3493 return QCBOR_SUCCESS;
3494}
3495
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003496
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003497/*
3498 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3499 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003500static inline QCBORError ExponentitateNU(int64_t nMantissa,
3501 int64_t nExponent,
3502 uint64_t *puResult,
3503 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003504{
3505 if(nMantissa < 0) {
3506 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3507 }
3508
3509 // Cast to unsigned is OK because of check for negative
3510 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3511 // Exponentiation is straight forward
3512 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3513}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003514
3515
3516/*
3517 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3518 */
3519static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3520 int64_t nExponent,
3521 uint64_t *puResult,
3522 fExponentiator pfExp)
3523{
3524 return (*pfExp)(uMantissa, nExponent, puResult);
3525}
3526
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003527#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3528
3529
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003530
3531
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003532#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003533
3534
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003535static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003536{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003537 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003538
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003539 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003540 const uint8_t *pByte = BigNum.ptr;
3541 size_t uLen = BigNum.len;
3542 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003543 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003544 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003545 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003546 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003547 }
3548
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003549 *pResult = uResult;
3550 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003551}
3552
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003553
Laurence Lundblade887add82020-05-17 05:50:34 -07003554static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003555{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003556 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003557}
3558
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003559
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003560static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003561{
3562 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003563 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3564 if(uError) {
3565 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003566 }
3567 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3568 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003569 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003570}
3571
3572
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003573static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003574{
3575 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003576 /* The negative integer furthest from zero for a C int64_t is
3577 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3578 negative number in CBOR is computed as -n - 1 where n is the
3579 encoded integer, where n is what is in the variable BigNum. When
3580 converting BigNum to a uint64_t, the maximum value is thus
3581 INT64_MAX, so that when it -n - 1 is applied to it the result will
3582 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003583
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003584 -n - 1 <= INT64_MIN.
3585 -n - 1 <= -INT64_MAX - 1
3586 n <= INT64_MAX.
3587 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003588 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003589 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003590 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003591 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003592
3593 /// Now apply -n - 1. The cast is safe because
3594 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3595 // is the largest positive integer that an int64_t can
3596 // represent. */
3597 *pnResult = -(int64_t)uResult - 1;
3598
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003599 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003600}
3601
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003602
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003603
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003604
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003605#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003606
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003607
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003608/*
3609Convert a integers and floats to an int64_t.
3610
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003611\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003612
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003613\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003614
3615\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3616
3617\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3618
3619*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003620static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003621{
3622 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003623 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003624 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003625#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003626 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003627 // TODO: what about under/overflow here?
3628 // Invokes the floating-point HW and/or compiler-added libraries
3629 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003630 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3631 *pnValue = llround(pItem->val.dfnum);
3632 } else {
3633 *pnValue = lroundf(pItem->val.fnum);
3634 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003635 if(fetestexcept(FE_INVALID)) {
3636 // TODO: better error code
3637 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3638 }
3639 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003640 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003641 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003642#else
3643 return QCBOR_ERR_HW_FLOAT_DISABLED;
3644#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003645 break;
3646
3647 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003648 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649 *pnValue = pItem->val.int64;
3650 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003651 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652 }
3653 break;
3654
3655 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003656 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003657 if(pItem->val.uint64 < INT64_MAX) {
3658 *pnValue = pItem->val.int64;
3659 } else {
3660 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3661 }
3662 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003663 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003664 }
3665 break;
3666
3667 default:
3668 return QCBOR_ERR_UNEXPECTED_TYPE;
3669 }
3670 return QCBOR_SUCCESS;
3671}
3672
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003673
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003674void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003675 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003676 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003677 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003678{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003679 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003680 return;
3681 }
3682
Laurence Lundbladee6430642020-03-14 21:15:44 -07003683 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003684 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3685 if(uError) {
3686 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003687 return;
3688 }
3689
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003690 if(pItem) {
3691 *pItem = Item;
3692 }
3693
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003694 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003695}
3696
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003697
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003698void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3699 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003700 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003701 int64_t *pnValue,
3702 QCBORItem *pItem)
3703{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003704 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003705 if(pMe->uLastError != QCBOR_SUCCESS) {
3706 return;
3707 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003708
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003709 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003710}
3711
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003712
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003713void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3714 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003715 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003716 int64_t *pnValue,
3717 QCBORItem *pItem)
3718{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003719 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003720 if(pMe->uLastError != QCBOR_SUCCESS) {
3721 return;
3722 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003723
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003724 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725}
3726
3727
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003728/*
3729 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003730
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003731 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003732
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003733 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003734
3735 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3736
3737 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3738
3739 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003740static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003741{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003742 switch(pItem->uDataType) {
3743
3744 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003745 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003746 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003747 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003748 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003749 }
3750 break;
3751
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003752 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003753 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003754 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003755 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003756 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003757 }
3758 break;
3759
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003760#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3761 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003762 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003763 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003764 pItem->val.expAndMantissa.nExponent,
3765 pnValue,
3766 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003767 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003768 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003769 }
3770 break;
3771
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003772 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003773 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003774 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003775 pItem->val.expAndMantissa.nExponent,
3776 pnValue,
3777 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003778 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003779 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003780 }
3781 break;
3782
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003783 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003784 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003785 int64_t nMantissa;
3786 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003787 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3788 if(uErr) {
3789 return uErr;
3790 }
3791 return ExponentiateNN(nMantissa,
3792 pItem->val.expAndMantissa.nExponent,
3793 pnValue,
3794 Exponentitate10);
3795 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003796 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003797 }
3798 break;
3799
3800 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003801 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003802 int64_t nMantissa;
3803 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003804 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3805 if(uErr) {
3806 return uErr;
3807 }
3808 return ExponentiateNN(nMantissa,
3809 pItem->val.expAndMantissa.nExponent,
3810 pnValue,
3811 Exponentitate10);
3812 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003813 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003814 }
3815 break;
3816
3817 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003818 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003819 int64_t nMantissa;
3820 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003821 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3822 if(uErr) {
3823 return uErr;
3824 }
3825 return ExponentiateNN(nMantissa,
3826 pItem->val.expAndMantissa.nExponent,
3827 pnValue,
3828 Exponentitate2);
3829 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003830 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003831 }
3832 break;
3833
3834 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003835 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003836 int64_t nMantissa;
3837 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003838 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3839 if(uErr) {
3840 return uErr;
3841 }
3842 return ExponentiateNN(nMantissa,
3843 pItem->val.expAndMantissa.nExponent,
3844 pnValue,
3845 Exponentitate2);
3846 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003847 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003848 }
3849 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003850#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3851
Laurence Lundbladee6430642020-03-14 21:15:44 -07003852
Laurence Lundbladec4537442020-04-14 18:53:22 -07003853 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003854 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003855}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003856
3857
Laurence Lundbladec4537442020-04-14 18:53:22 -07003858/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003859 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003860 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003861void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003862{
3863 QCBORItem Item;
3864
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003865 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003866
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003867 if(pMe->uLastError == QCBOR_SUCCESS) {
3868 // The above conversion succeeded
3869 return;
3870 }
3871
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003872 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003873 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003874 return;
3875 }
3876
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003877 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003878}
3879
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003880
3881/*
3882Public function, see header qcbor/qcbor_decode.h file
3883*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003884void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
3885 int64_t nLabel,
3886 uint32_t uConvertTypes,
3887 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003888{
3889 QCBORItem Item;
3890
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003891 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003892
3893 if(pMe->uLastError == QCBOR_SUCCESS) {
3894 // The above conversion succeeded
3895 return;
3896 }
3897
3898 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3899 // The above conversion failed in a way that code below can't correct
3900 return;
3901 }
3902
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003903 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003904}
3905
3906
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003907/*
3908Public function, see header qcbor/qcbor_decode.h file
3909*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003910void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
3911 const char *szLabel,
3912 uint32_t uConvertTypes,
3913 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003914{
3915 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003916 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003917
3918 if(pMe->uLastError == QCBOR_SUCCESS) {
3919 // The above conversion succeeded
3920 return;
3921 }
3922
3923 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3924 // The above conversion failed in a way that code below can't correct
3925 return;
3926 }
3927
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003928 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003929}
3930
3931
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003932static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003933{
3934 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003935 case QCBOR_TYPE_DOUBLE:
3936 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003937#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003938 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
3939 // TODO: this code needs work
3940 feclearexcept(FE_ALL_EXCEPT);
3941 double dRounded = round(pItem->val.dfnum);
3942 // TODO: over/underflow
3943 if(fetestexcept(FE_INVALID)) {
3944 // TODO: better error code
3945 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3946 } else if(isnan(dRounded)) {
3947 // TODO: better error code
3948 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3949 } else if(dRounded >= 0) {
3950 *puValue = (uint64_t)dRounded;
3951 } else {
3952 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3953 }
3954 } else {
3955 return QCBOR_ERR_UNEXPECTED_TYPE;
3956 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003957#else
3958 return QCBOR_ERR_HW_FLOAT_DISABLED;
3959#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003960 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003961
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003962 case QCBOR_TYPE_INT64:
3963 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
3964 if(pItem->val.int64 >= 0) {
3965 *puValue = (uint64_t)pItem->val.int64;
3966 } else {
3967 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3968 }
3969 } else {
3970 return QCBOR_ERR_UNEXPECTED_TYPE;
3971 }
3972 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003973
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003974 case QCBOR_TYPE_UINT64:
3975 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
3976 *puValue = pItem->val.uint64;
3977 } else {
3978 return QCBOR_ERR_UNEXPECTED_TYPE;
3979 }
3980 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003981
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003982 default:
3983 return QCBOR_ERR_UNEXPECTED_TYPE;
3984 }
3985
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986 return QCBOR_SUCCESS;
3987}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003988
3989
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003990void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003991 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003992 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003993 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003994{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003995 if(pMe->uLastError != QCBOR_SUCCESS) {
3996 return;
3997 }
3998
Laurence Lundbladec4537442020-04-14 18:53:22 -07003999 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004000
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004001 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4002 if(uError) {
4003 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004004 return;
4005 }
4006
Laurence Lundbladea826c502020-05-10 21:07:00 -07004007 if(pItem) {
4008 *pItem = Item;
4009 }
4010
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004011 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004012}
4013
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004014
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004015void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4016 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004018 uint64_t *puValue,
4019 QCBORItem *pItem)
4020{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004021 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004022 if(pMe->uLastError != QCBOR_SUCCESS) {
4023 return;
4024 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004025
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004026 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004027}
4028
4029
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004030void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004031 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004032 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004033 uint64_t *puValue,
4034 QCBORItem *pItem)
4035{
4036 if(pMe->uLastError != QCBOR_SUCCESS) {
4037 return;
4038 }
4039
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004040 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004041 if(pMe->uLastError != QCBOR_SUCCESS) {
4042 return;
4043 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004045 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004046}
4047
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004048
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004049/*
4050 Public function, see header qcbor/qcbor_decode.h file
4051*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004052static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004053{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004054 switch(pItem->uDataType) {
4055
4056 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004058 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4059 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004060 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004061 }
4062 break;
4063
4064 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004066 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4067 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004069 }
4070 break;
4071
4072#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4073
4074 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004075 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004076 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004077 pItem->val.expAndMantissa.nExponent,
4078 puValue,
4079 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004080 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004082 }
4083 break;
4084
4085 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004086 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004087 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4088 pItem->val.expAndMantissa.nExponent,
4089 puValue,
4090 Exponentitate2);
4091 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004093 }
4094 break;
4095
4096 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004097 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004098 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004099 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004100 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004101 if(uErr != QCBOR_SUCCESS) {
4102 return uErr;
4103 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004104 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004105 pItem->val.expAndMantissa.nExponent,
4106 puValue,
4107 Exponentitate10);
4108 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004110 }
4111 break;
4112
4113 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004114 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004115 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4116 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004117 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118 }
4119 break;
4120
4121 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004123 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004124 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004125 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004126 if(uErr != QCBOR_SUCCESS) {
4127 return uErr;
4128 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004129 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004130 pItem->val.expAndMantissa.nExponent,
4131 puValue,
4132 Exponentitate2);
4133 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004134 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004135 }
4136 break;
4137
4138 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004139 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004140 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4141 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004142 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004143 }
4144 break;
4145#endif
4146 default:
4147 return QCBOR_ERR_UNEXPECTED_TYPE;
4148 }
4149}
4150
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004151
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004152/*
4153 Public function, see header qcbor/qcbor_decode.h file
4154*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004156{
4157 QCBORItem Item;
4158
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004159 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004160
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004161 if(pMe->uLastError == QCBOR_SUCCESS) {
4162 // The above conversion succeeded
4163 return;
4164 }
4165
4166 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4167 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004168 return;
4169 }
4170
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004172}
4173
Laurence Lundbladec4537442020-04-14 18:53:22 -07004174
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004175/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004176 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004178void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004179{
4180 QCBORItem Item;
4181
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004182 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004183
4184 if(pMe->uLastError == QCBOR_SUCCESS) {
4185 // The above conversion succeeded
4186 return;
4187 }
4188
4189 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4190 // The above conversion failed in a way that code below can't correct
4191 return;
4192 }
4193
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004194 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004195}
4196
4197
4198/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004199 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004200*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004201void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004202{
4203 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004205
4206 if(pMe->uLastError == QCBOR_SUCCESS) {
4207 // The above conversion succeeded
4208 return;
4209 }
4210
4211 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4212 // The above conversion failed in a way that code below can't correct
4213 return;
4214 }
4215
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217}
4218
4219
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221{
4222 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004223 case QCBOR_TYPE_FLOAT:
4224#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4225 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4226 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4227 *pdValue = (double)pItem->val.fnum;
4228 } else {
4229 return QCBOR_ERR_UNEXPECTED_TYPE;
4230 }
4231 }
4232#else
4233 return QCBOR_ERR_HW_FLOAT_DISABLED;
4234#endif
4235 break;
4236
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004237 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4239 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004240 *pdValue = pItem->val.dfnum;
4241 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004242 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004243 }
4244 }
4245 break;
4246
4247 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004248#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004249 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004250 // TODO: how does this work?
4251 *pdValue = (double)pItem->val.int64;
4252
4253 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004254 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004255 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004256#else
4257 return QCBOR_ERR_HW_FLOAT_DISABLED;
4258#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004259 break;
4260
4261 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004262#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004263 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004264 *pdValue = (double)pItem->val.uint64;
4265 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004266 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004267 }
4268 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004269#else
4270 return QCBOR_ERR_HW_FLOAT_DISABLED;
4271#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272
4273 default:
4274 return QCBOR_ERR_UNEXPECTED_TYPE;
4275 }
4276
4277 return QCBOR_SUCCESS;
4278}
4279
4280
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004281void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004282 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004283 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004284 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004285{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004286 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004287 return;
4288 }
4289
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004290 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004291
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004292 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004293 if(uError) {
4294 pMe->uLastError = (uint8_t)uError;
4295 return;
4296 }
4297
4298 if(pItem) {
4299 *pItem = Item;
4300 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004301
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004302 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004303}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004304
Laurence Lundbladec4537442020-04-14 18:53:22 -07004305
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004306void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4307 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004308 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004309 double *pdValue,
4310 QCBORItem *pItem)
4311{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004312 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004313 if(pMe->uLastError != QCBOR_SUCCESS) {
4314 return;
4315 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004316
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004317 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004318}
4319
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004320
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004321void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4322 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004323 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004324 double *pdValue,
4325 QCBORItem *pItem)
4326{
4327 if(pMe->uLastError != QCBOR_SUCCESS) {
4328 return;
4329 }
4330
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004331 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004332 if(pMe->uLastError != QCBOR_SUCCESS) {
4333 return;
4334 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004336 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004337}
4338
4339
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004340#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004341static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4342{
4343 double dResult;
4344
4345 dResult = 0.0;
4346 const uint8_t *pByte = BigNum.ptr;
4347 size_t uLen = BigNum.len;
4348 /* This will overflow and become the float value INFINITY if the number
4349 is too large to fit. No error will be logged.
4350 TODO: should an error be logged? */
4351 while(uLen--) {
4352 dResult = (dResult * 256.0) + (double)*pByte++;
4353 }
4354
4355 return dResult;
4356}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004357#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4358
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004359
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004360static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004361{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004362#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004363 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004364 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4365
4366 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004367 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004368
4369#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004371 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372 // TODO: rounding and overflow errors
4373 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4374 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4375 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004376 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004377 }
4378 break;
4379
4380 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004381 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004382 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4383 exp2((double)pItem->val.expAndMantissa.nExponent);
4384 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004385 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004386 }
4387 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004388#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389
4390 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004391 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004392 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4393 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004394 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395 }
4396 break;
4397
4398 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004399 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004400 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004401 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004402 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004403 }
4404 break;
4405
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004406#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004408 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4410 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4411 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004412 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413 }
4414 break;
4415
4416 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004417 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4419 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4420 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004421 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422 }
4423 break;
4424
4425 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004426 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004427 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4428 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4429 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004430 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004431 }
4432 break;
4433
4434 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004435 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004436 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4438 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440 }
4441 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004442#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4443
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004444
4445 default:
4446 return QCBOR_ERR_UNEXPECTED_TYPE;
4447 }
4448
4449 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004450
4451#else
4452 (void)pItem;
4453 (void)uConvertTypes;
4454 (void)pdValue;
4455 return QCBOR_ERR_HW_FLOAT_DISABLED;
4456#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4457
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458}
4459
4460
4461/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004462 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004463*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004464void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004465{
4466
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004467 QCBORItem Item;
4468
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004469 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004470
4471 if(pMe->uLastError == QCBOR_SUCCESS) {
4472 // The above conversion succeeded
4473 return;
4474 }
4475
4476 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4477 // The above conversion failed in a way that code below can't correct
4478 return;
4479 }
4480
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004482}
4483
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484
4485/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004486 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004489{
4490 QCBORItem Item;
4491
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004492 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004493
4494 if(pMe->uLastError == QCBOR_SUCCESS) {
4495 // The above conversion succeeded
4496 return;
4497 }
4498
4499 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4500 // The above conversion failed in a way that code below can't correct
4501 return;
4502 }
4503
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004505}
4506
4507
4508/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004509 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004510*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004511void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512{
4513 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004514 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004515
4516 if(pMe->uLastError == QCBOR_SUCCESS) {
4517 // The above conversion succeeded
4518 return;
4519 }
4520
4521 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4522 // The above conversion failed in a way that code below can't correct
4523 return;
4524 }
4525
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004526 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004527}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004528
4529
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004530
4531
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004532#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004533static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4534{
4535 while((uInt & 0xff00000000000000UL) == 0) {
4536 uInt = uInt << 8;
4537 };
4538
4539 UsefulOutBuf UOB;
4540
4541 UsefulOutBuf_Init(&UOB, Buffer);
4542
4543 while(uInt) {
4544 const uint64_t xx = uInt & 0xff00000000000000UL;
4545 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4546 uInt = uInt << 8;
4547 (void)xx;
4548 }
4549
4550 return UsefulOutBuf_OutUBuf(&UOB);
4551}
4552
4553
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004554static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4555 TagSpecification TagSpec,
4556 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004557{
4558 QCBORError uErr;
4559 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004560 while(1) {
4561 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4562 if(uErr != QCBOR_SUCCESS) {
4563 goto Done;
4564 }
4565
4566 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4567 break; // Successful exit. Moving on to finish decoding.
4568 }
4569
4570 // The item is an array, which means an undecoded
4571 // mantissa and exponent, so decode it. It will then
4572 // have a different type and exit the loop if.
4573 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4574 if(uErr != QCBOR_SUCCESS) {
4575 goto Done;
4576 }
4577
4578 // Second time around, the type must match.
4579 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
4580 }
4581Done:
4582 return uErr;
4583}
4584
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004585
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004586static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004587 TagSpecification TagSpec,
4588 QCBORItem *pItem,
4589 int64_t *pnMantissa,
4590 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004591{
4592 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004593
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004594 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004595 if(uErr != QCBOR_SUCCESS) {
4596 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004597 }
4598
4599 switch (pItem->uDataType) {
4600
4601 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004602 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004603 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4604 *pnExponent = pItem->val.expAndMantissa.nExponent;
4605 break;
4606
4607 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004608 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004609 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004610 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004611 break;
4612
4613 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004614 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004615 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004616 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004617 break;
4618
4619 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004620 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004621 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004622
4623 Done:
4624 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004625}
4626
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004627
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004628static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004629 TagSpecification TagSpec,
4630 QCBORItem *pItem,
4631 UsefulBuf BufferForMantissa,
4632 UsefulBufC *pMantissa,
4633 bool *pbIsNegative,
4634 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004635{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004636 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004637
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004638 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004639 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004640 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004641 }
4642
4643 uint64_t uMantissa;
4644
4645 switch (pItem->uDataType) {
4646
4647 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004648 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004649 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4650 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4651 *pbIsNegative = false;
4652 } else {
4653 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4654 *pbIsNegative = true;
4655 }
4656 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4657 *pnExponent = pItem->val.expAndMantissa.nExponent;
4658 break;
4659
4660 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004661 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004662 *pnExponent = pItem->val.expAndMantissa.nExponent;
4663 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4664 *pbIsNegative = false;
4665 break;
4666
4667 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004668 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004669 *pnExponent = pItem->val.expAndMantissa.nExponent;
4670 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4671 *pbIsNegative = true;
4672 break;
4673
4674 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004675 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004676 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004677
4678Done:
4679 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004680}
4681
4682
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004683/*
4684 Public function, see header qcbor/qcbor_decode.h file
4685*/
4686void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4687 uint8_t uTagRequirement,
4688 int64_t *pnMantissa,
4689 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004690{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004691 if(pMe->uLastError != QCBOR_SUCCESS) {
4692 return;
4693 }
4694
4695 QCBORItem Item;
4696 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4697 if(uError) {
4698 pMe->uLastError = (uint8_t)uError;
4699 return;
4700 }
4701
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004702 const TagSpecification TagSpec =
4703 {
4704 uTagRequirement,
4705 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4706 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4707 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004708
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004709 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004710}
4711
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004712
4713/*
4714 Public function, see header qcbor/qcbor_decode.h file
4715*/
4716void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004717 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004718 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004719 int64_t *pnMantissa,
4720 int64_t *pnExponent)
4721{
4722 if(pMe->uLastError != QCBOR_SUCCESS) {
4723 return;
4724 }
4725
4726 QCBORItem Item;
4727 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4728
4729 const TagSpecification TagSpec =
4730 {
4731 uTagRequirement,
4732 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4733 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4734 };
4735
4736 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4737}
4738
4739
4740/*
4741 Public function, see header qcbor/qcbor_decode.h file
4742*/
4743void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004744 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004745 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004746 int64_t *pnMantissa,
4747 int64_t *pnExponent)
4748{
4749 if(pMe->uLastError != QCBOR_SUCCESS) {
4750 return;
4751 }
4752
4753 QCBORItem Item;
4754 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4755
4756 const TagSpecification TagSpec =
4757 {
4758 uTagRequirement,
4759 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4760 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4761 };
4762
4763 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4764}
4765
4766
4767/*
4768 Public function, see header qcbor/qcbor_decode.h file
4769*/
4770void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4771 uint8_t uTagRequirement,
4772 UsefulBuf MantissaBuffer,
4773 UsefulBufC *pMantissa,
4774 bool *pbMantissaIsNegative,
4775 int64_t *pnExponent)
4776{
4777 if(pMe->uLastError != QCBOR_SUCCESS) {
4778 return;
4779 }
4780
4781 QCBORItem Item;
4782 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4783 if(uError) {
4784 pMe->uLastError = (uint8_t)uError;
4785 return;
4786 }
4787
4788 const TagSpecification TagSpec =
4789 {
4790 uTagRequirement,
4791 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4792 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4793 };
4794
4795 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4796}
4797
4798
4799/*
4800 Public function, see header qcbor/qcbor_decode.h file
4801*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004802void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004803 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004804 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004805 UsefulBuf BufferForMantissa,
4806 UsefulBufC *pMantissa,
4807 bool *pbIsNegative,
4808 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004809{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004810 if(pMe->uLastError != QCBOR_SUCCESS) {
4811 return;
4812 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004813
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004814 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004815 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004816 if(pMe->uLastError != QCBOR_SUCCESS) {
4817 return;
4818 }
4819
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004820 const TagSpecification TagSpec =
4821 {
4822 uTagRequirement,
4823 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4824 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4825 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004826
4827 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004828}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004829
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004830
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004831/*
4832 Public function, see header qcbor/qcbor_decode.h file
4833*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004834void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004835 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004836 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004837 UsefulBuf BufferForMantissa,
4838 UsefulBufC *pMantissa,
4839 bool *pbIsNegative,
4840 int64_t *pnExponent)
4841{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004842 if(pMe->uLastError != QCBOR_SUCCESS) {
4843 return;
4844 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004845
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004846 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004847 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4848 if(pMe->uLastError != QCBOR_SUCCESS) {
4849 return;
4850 }
4851
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004852 const TagSpecification TagSpec =
4853 {
4854 uTagRequirement,
4855 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4856 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4857 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004858
4859 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4860}
4861
4862
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004863/*
4864 Public function, see header qcbor/qcbor_decode.h file
4865*/
4866void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
4867 uint8_t uTagRequirement,
4868 int64_t *pnMantissa,
4869 int64_t *pnExponent)
4870{
4871 if(pMe->uLastError != QCBOR_SUCCESS) {
4872 return;
4873 }
4874
4875 QCBORItem Item;
4876 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4877 if(uError) {
4878 pMe->uLastError = (uint8_t)uError;
4879 return;
4880 }
4881 const TagSpecification TagSpec =
4882 {
4883 uTagRequirement,
4884 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4885 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4886 };
4887
4888 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4889}
4890
4891
4892/*
4893 Public function, see header qcbor/qcbor_decode.h file
4894*/
4895void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004896 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004897 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004898 int64_t *pnMantissa,
4899 int64_t *pnExponent)
4900{
4901 if(pMe->uLastError != QCBOR_SUCCESS) {
4902 return;
4903 }
4904
4905 QCBORItem Item;
4906 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4907 if(pMe->uLastError != QCBOR_SUCCESS) {
4908 return;
4909 }
4910
4911 const TagSpecification TagSpec =
4912 {
4913 uTagRequirement,
4914 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4915 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4916 };
4917
4918 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4919}
4920
4921
4922/*
4923 Public function, see header qcbor/qcbor_decode.h file
4924*/
4925void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004926 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004927 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004928 int64_t *pnMantissa,
4929 int64_t *pnExponent)
4930{
4931 if(pMe->uLastError != QCBOR_SUCCESS) {
4932 return;
4933 }
4934
4935 QCBORItem Item;
4936 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4937 if(pMe->uLastError != QCBOR_SUCCESS) {
4938 return;
4939 }
4940
4941 const TagSpecification TagSpec =
4942 {
4943 uTagRequirement,
4944 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4945 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4946 };
4947
4948 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4949}
4950
4951
4952/*
4953 Public function, see header qcbor/qcbor_decode.h file
4954*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004955void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
4956 uint8_t uTagRequirement,
4957 UsefulBuf MantissaBuffer,
4958 UsefulBufC *pMantissa,
4959 bool *pbMantissaIsNegative,
4960 int64_t *pnExponent)
4961{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004962 if(pMe->uLastError != QCBOR_SUCCESS) {
4963 return;
4964 }
4965
4966 QCBORItem Item;
4967 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4968 if(uError) {
4969 pMe->uLastError = (uint8_t)uError;
4970 return;
4971 }
4972
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004973 const TagSpecification TagSpec =
4974 {
4975 uTagRequirement,
4976 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4977 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4978 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004979
4980 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004981}
4982
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004983
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004984/*
4985 Public function, see header qcbor/qcbor_decode.h file
4986*/
4987void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004988 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004989 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004990 UsefulBuf BufferForMantissa,
4991 UsefulBufC *pMantissa,
4992 bool *pbIsNegative,
4993 int64_t *pnExponent)
4994{
4995 if(pMe->uLastError != QCBOR_SUCCESS) {
4996 return;
4997 }
4998
4999 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005000 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5001 if(pMe->uLastError != QCBOR_SUCCESS) {
5002 return;
5003 }
5004
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005005 const TagSpecification TagSpec =
5006 {
5007 uTagRequirement,
5008 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5009 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5010 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005011
5012 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5013}
5014
5015
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005016/*
5017 Public function, see header qcbor/qcbor_decode.h file
5018*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005019void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005020 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005021 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005022 UsefulBuf BufferForMantissa,
5023 UsefulBufC *pMantissa,
5024 bool *pbIsNegative,
5025 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005026{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005027 if(pMe->uLastError != QCBOR_SUCCESS) {
5028 return;
5029 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005030
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005031 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5033 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005034 return;
5035 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005036
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005037 const TagSpecification TagSpec =
5038 {
5039 uTagRequirement,
5040 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5041 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5042 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005043
5044 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005045}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005046
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005047#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */