blob: b5140c12113393b6201e883c6764e18467358c8d [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 Lundblade3ed0bca2020-07-14 22:50:10 -0700800 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700801 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700802 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
803 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700804#else
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700805 nReturn = QCBOR_ERR_HALF_PRECISION_UNSUPPORTED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700806#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700807 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700808 case SINGLE_PREC_FLOAT:
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700809#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700810 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700811 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700812 pDecodedItem->val.dfnum = IEEE754_FloatToDouble((uint32_t)uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700813 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700814#else
815 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
816 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
817#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700818 break;
819 case DOUBLE_PREC_FLOAT:
820 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700821 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700822 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800823
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700824 case CBOR_SIMPLEV_FALSE: // 20
825 case CBOR_SIMPLEV_TRUE: // 21
826 case CBOR_SIMPLEV_NULL: // 22
827 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700828 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700829 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800830
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831 case CBOR_SIMPLEV_ONEBYTE: // 24
832 if(uNumber <= CBOR_SIMPLE_BREAK) {
833 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700834 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 goto Done;
836 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800837 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840 default: // 0-19
841 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800842 /*
843 DecodeTypeAndNumber will make uNumber equal to
844 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
845 safe because the 2, 4 and 8 byte lengths of uNumber are in
846 the double/float cases above
847 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848 pDecodedItem->val.uSimple = (uint8_t)uNumber;
849 break;
850 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700852Done:
853 return nReturn;
854}
855
856
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530858 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700859 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800860inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
861 int nMajorType,
862 uint64_t uStrLen,
863 UsefulInputBuf *pUInBuf,
864 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700866 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800867
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
869 // This check makes the casts to size_t below safe.
870
871 // 4 bytes less than the largest sizeof() so this can be tested by
872 // putting a SIZE_MAX length in the CBOR test input (no one will
873 // care the limit on strings is 4 bytes shorter).
874 if(uStrLen > SIZE_MAX-4) {
875 nReturn = QCBOR_ERR_STRING_TOO_LONG;
876 goto Done;
877 }
878
879 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530880 if(UsefulBuf_IsNULLC(Bytes)) {
881 // Failed to get the bytes for this string item
882 nReturn = QCBOR_ERR_HIT_END;
883 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530885
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800886 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530887 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800888 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700890 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891 goto Done;
892 }
893 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800894 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530895 } else {
896 // Normal case with no string allocator
897 pDecodedItem->val.string = Bytes;
898 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800899 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800900 // Cast because ternary operator causes promotion to integer
901 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
902 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530904Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700905 return nReturn;
906}
907
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700908
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910
911
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700912
913
Laurence Lundbladeee851742020-01-08 08:37:05 -0800914// Make sure the constants align as this is assumed by
915// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
917#error QCBOR_TYPE_ARRAY value not lined up with major type
918#endif
919#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
920#error QCBOR_TYPE_MAP value not lined up with major type
921#endif
922
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800924 This gets a single data item and decodes it including preceding
925 optional tagging. This does not deal with arrays and maps and nesting
926 except to decode the data item introducing them. Arrays and maps are
927 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundbladeee851742020-01-08 08:37:05 -0800929 Errors detected here include: an array that is too long to decode,
930 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800932static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
933 QCBORItem *pDecodedItem,
934 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700935{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700936 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundbladeee851742020-01-08 08:37:05 -0800938 /*
939 Get the major type and the number. Number could be length of more
940 bytes or the value depending on the major type nAdditionalInfo is
941 an encoding of the length of the uNumber and is needed to decode
942 floats and doubles
943 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800944 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700945 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800946 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700948 memset(pDecodedItem, 0, sizeof(QCBORItem));
949
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800951
Laurence Lundbladeee851742020-01-08 08:37:05 -0800952 // Error out here if we got into trouble on the type and number. The
953 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700954 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700956 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundbladeee851742020-01-08 08:37:05 -0800958 // At this point the major type and the value are valid. We've got
959 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800960 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
962 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700964 nReturn = QCBOR_ERR_BAD_INT;
965 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
971 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800972 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
973 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
974 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
975 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530976 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800978 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 }
980 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
983 case CBOR_MAJOR_TYPE_MAP: // Major type 5
984 // Record the number of items in the array or map
985 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
986 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
987 goto Done;
988 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700990 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992 // type conversion OK because of check above
993 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800995 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
997 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001001 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001002 nReturn = QCBOR_ERR_BAD_INT;
1003 } else {
1004 pDecodedItem->val.uTagV = uNumber;
1005 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
1006 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladeee851742020-01-08 08:37:05 -08001009 case CBOR_MAJOR_TYPE_SIMPLE:
1010 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001011 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladeee851742020-01-08 08:37:05 -08001014 default:
1015 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 nReturn = QCBOR_ERR_UNSUPPORTED;
1017 break;
1018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020Done:
1021 return nReturn;
1022}
1023
1024
1025
1026/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001027 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001028 individual chunk items together into one QCBORItem using the string
1029 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301031 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001033static inline QCBORError
1034GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001036 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001037
1038 // Get pointer to string allocator. First use is to pass it to
1039 // GetNext_Item() when option is set to allocate for *every* string.
1040 // Second use here is to allocate space to coallese indefinite
1041 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001042 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1043 &(me->StringAllocator) :
1044 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001046 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001047 nReturn = GetNext_Item(&(me->InBuf),
1048 pDecodedItem,
1049 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050 if(nReturn) {
1051 goto Done;
1052 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301055 // code in this function from here down can be eliminated. Run tests, except
1056 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001057
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001058 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001059 const uint8_t uStringType = pDecodedItem->uDataType;
1060 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 goto Done; // no need to do any work here on non-string types
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001064 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301065 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001066 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001067 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301069 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001070 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1072 goto Done;
1073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001075 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001076 UsefulBufC FullString = NULLUsefulBufC;
1077
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001079 // Get item for next chunk
1080 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001081 // NULL string allocator passed here. Do not need to allocate
1082 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001083 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001085 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001087
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301088 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001089 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001090 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301092 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 break;
1094 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001096 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301097 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001098 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001099 if(StringChunkItem.uDataType != uStringType ||
1100 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001101 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 break;
1103 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001104
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301105 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001106 // The first time throurgh FullString.ptr is NULL and this is
1107 // equivalent to StringAllocator_Allocate()
1108 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1109 UNCONST_POINTER(FullString.ptr),
1110 FullString.len + StringChunkItem.val.string.len);
1111
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301113 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001114 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 break;
1116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001118 // Copy new string chunk at the end of string so far.
1119 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001122 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1123 // Getting the item failed, clean up the allocated memory
1124 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001126
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001127Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001128 return nReturn;
1129}
1130
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001132static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1133 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001134 return uTagVal;
1135 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001136 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001137 return me->auMappedTags[x];
1138 }
1139}
1140
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001141/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001142 Gets all optional tag data items preceding a data item that is not an
1143 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001144 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001145static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001146GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001147{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001148 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001149
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001150 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1151 CBOR_TAG_INVALID16,
1152 CBOR_TAG_INVALID16,
1153 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001154
Laurence Lundblade59289e52019-12-30 13:44:37 -08001155 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001156 for(;;) {
1157 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001158 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001159 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001161
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001162 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1163 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001164 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001165 break;
1166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 // Is there room for the tag in the tags list?
1169 size_t uTagIndex;
1170 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001171 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001172 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001173 }
1174 }
1175 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001176 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001180 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001181 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001182 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001183 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001184 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001185 break;
1186 }
1187 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001188 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001189 break;
1190 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001192 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1193 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001194 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1195 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001196 }
1197
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001198 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001199 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001200 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001201
1202 } else {
1203 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001204 }
1205 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001206
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001207Done:
1208 return nReturn;
1209}
1210
1211
1212/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001213 This layer takes care of map entries. It combines the label and data
1214 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001215 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001216static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001218{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001219 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001220 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001221 if(nReturn)
1222 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001223
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001224 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001225 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001226 goto Done;
1227 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001229 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1230 // In a map and caller wants maps decoded, not treated as arrays
1231
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001232 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001233 // If in a map and the right decoding mode, get the label
1234
Laurence Lundbladeee851742020-01-08 08:37:05 -08001235 // Save label in pDecodedItem and get the next which will
1236 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001237 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001239 if(nReturn)
1240 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001241
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301242 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001243
1244 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1245 // strings are always good labels
1246 pDecodedItem->label.string = LabelItem.val.string;
1247 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1248 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001249 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001250 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1251 goto Done;
1252 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1253 pDecodedItem->label.int64 = LabelItem.val.int64;
1254 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1255 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1256 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1257 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1258 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1259 pDecodedItem->label.string = LabelItem.val.string;
1260 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1261 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1262 } else {
1263 // label is not an int or a string. It is an arrray
1264 // or a float or such and this implementation doesn't handle that.
1265 // Also, tags on labels are ignored.
1266 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1267 goto Done;
1268 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001269 }
1270 } else {
1271 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001272 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1273 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1274 goto Done;
1275 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001276 // Decoding a map as an array
1277 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001278 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1279 // Cast is needed because of integer promotion
1280 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001281 }
1282 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001283
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001284Done:
1285 return nReturn;
1286}
1287
1288
Laurence Lundblade02625d42020-06-25 14:41:41 -07001289/*
1290 See if next item is a CBOR break. If it is, it is consumed,
1291 if not it is not consumed.
1292*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001293static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001294NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1295{
1296 *pbNextIsBreak = false;
1297 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001298 QCBORItem Peek;
1299 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1300 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1301 if(uReturn != QCBOR_SUCCESS) {
1302 return uReturn;
1303 }
1304 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001305 // It is not a break, rewind so it can be processed normally.
1306 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001307 } else {
1308 *pbNextIsBreak = true;
1309 }
1310 }
1311
1312 return QCBOR_SUCCESS;
1313}
1314
1315
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001316/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001317 An item was just consumed, now figure out if it was the
1318 end of an array or map that can be closed out. That
1319 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001321static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001322{
1323 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001324
Laurence Lundblade642282a2020-06-23 12:00:33 -07001325 /* This loops ascending nesting levels as long as there is ascending to do */
1326 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1327
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001328 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001329 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001330 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1331 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001332 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001333 break;
1334 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001335 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001337 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001338 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001339 bool bIsBreak = false;
1340 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1341 if(uReturn != QCBOR_SUCCESS) {
1342 goto Done;
1343 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001344
1345 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001346 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001347 break;
1348 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001349
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001350 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351 /*
1352 Break occurred inside a bstr-wrapped CBOR or
1353 in the top level sequence. This is always an
1354 error because neither are an indefinte length
1355 map/array.
1356 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001357 uReturn = QCBOR_ERR_BAD_BREAK;
1358 goto Done;
1359 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001360
Laurence Lundblade02625d42020-06-25 14:41:41 -07001361 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001362 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001363
Laurence Lundblade02625d42020-06-25 14:41:41 -07001364 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001365
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001366 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001367 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001368 /* 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 -07001369 if(bMarkEnd) {
1370 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001371 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001372
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001373 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001374 break;
1375 }
1376
1377 /* Finally, actually ascend one level. */
1378 DecodeNesting_Ascend(&(pMe->nesting));
1379 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001380
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001381 uReturn = QCBOR_SUCCESS;
1382
1383Done:
1384 return uReturn;
1385}
1386
1387
1388/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001389 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1391 indefinte length maps and arrays by looking at the item count or
1392 finding CBOR breaks. It detects the ends of the top-level sequence
1393 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001394 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001395static QCBORError
1396QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001397{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001398 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001399 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001400
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401 /*
1402 If out of bytes to consume, it is either the end of the top-level
1403 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001404
Laurence Lundblade642282a2020-06-23 12:00:33 -07001405 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1406 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1407 CBOR is exited, the length is set back to the top-level's length
1408 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001409 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001410 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001411 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001412 goto Done;
1413 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001414
Laurence Lundblade642282a2020-06-23 12:00:33 -07001415 /*
1416 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001417 array. The check for the end of an indefinite length array is
1418 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001419 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001420 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001421 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001422 goto Done;
1423 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001424
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001425 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001426 uReturn = GetNext_MapEntry(me, pDecodedItem);
1427 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001428 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001429 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301430
Laurence Lundblade642282a2020-06-23 12:00:33 -07001431 /*
1432 Breaks ending arrays/maps are always processed at the end of this
1433 function. They should never show up here.
1434 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301435 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001436 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301437 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301438 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001439
Laurence Lundblade642282a2020-06-23 12:00:33 -07001440 /*
1441 Record the nesting level for this data item before processing any
1442 of decrementing and descending.
1443 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001444 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001445
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001447 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001448 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001449 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001450 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001451
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001452 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001453 of in the next chunk of code.
1454
1455 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456 encloses them so a decrement needs to be done for them too, but
1457 that is done only when all the items in them have been
1458 processed, not when they are opened with the exception of an
1459 empty map or array.
1460 */
1461 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1462 pDecodedItem->uDataType,
1463 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001464 if(uReturn != QCBOR_SUCCESS) {
1465 goto Done;
1466 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001467 }
1468
Laurence Lundblade02625d42020-06-25 14:41:41 -07001469 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1470 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1471 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001472 /*
1473 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001474 - A non-aggregate like an integer or string
1475 - An empty definite length map or array
1476 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001478 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001479 definite length map/array and break detection for an indefinite
1480 length map/array. If the end of the map/array was reached, then
1481 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001482 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001483 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001484 if(uReturn) {
1485 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001486 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301487 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001488
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001489 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001490 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001491 Tell the caller what level is next. This tells them what
1492 maps/arrays were closed out and makes it possible for them to
1493 reconstruct the tree with just the information returned in
1494 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001496 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001497 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001498 pDecodedItem->uNextNestLevel = 0;
1499 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001500 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001501 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001502
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001503Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001504 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001505 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001506 memset(pDecodedItem, 0, sizeof(QCBORItem));
1507 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001508 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001509}
1510
1511
Laurence Lundblade59289e52019-12-30 13:44:37 -08001512/*
1513 Mostly just assign the right data type for the date string.
1514 */
1515inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1516{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001517 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1518 return QCBOR_ERR_BAD_OPT_TAG;
1519 }
1520
1521 const UsefulBufC Temp = pDecodedItem->val.string;
1522 pDecodedItem->val.dateString = Temp;
1523 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1524 return QCBOR_SUCCESS;
1525}
1526
1527
1528/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001529 The epoch formatted date. Turns lots of different forms of encoding
1530 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001531 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001532static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001533{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001534 QCBORError nReturn = QCBOR_SUCCESS;
1535
1536 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1537
1538 switch (pDecodedItem->uDataType) {
1539
1540 case QCBOR_TYPE_INT64:
1541 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1542 break;
1543
1544 case QCBOR_TYPE_UINT64:
1545 if(pDecodedItem->val.uint64 > INT64_MAX) {
1546 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1547 goto Done;
1548 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001549 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001550 break;
1551
1552 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001553 case QCBOR_TYPE_FLOAT:
1554#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001555 {
1556 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001557 // conversion to an int64_t to be able to detect doubles that
1558 // are too large to fit into an int64_t. A double has 52
1559 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1560 // to a double actually causes a round up which is bad and
1561 // wrong for the comparison because it will allow conversion
1562 // of doubles that can't fit into a uint64_t. To remedy this
1563 // INT64_MAX - 0x7ff is used as the cutoff point because if
1564 // that value rounds up in conversion to double it will still
1565 // be less than INT64_MAX. 0x7ff is picked because it has 11
1566 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001567 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001568 // INT64_MAX seconds is on the order of 10 billion years, and
1569 // the earth is less than 5 billion years old, so for most
1570 // uses this conversion error won't occur even though doubles
1571 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001572 //
1573 // Without the 0x7ff there is a ~30 minute range of time
1574 // values 10 billion years in the past and in the future
Laurence Lundblade9682a532020-06-06 18:33:04 -07001575 // where this this code would go wrong and some compilers
1576 // will generate warnings or errors.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001577 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1578 pDecodedItem->val.dfnum :
1579 (double)pDecodedItem->val.fnum;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001580 if(d > (double)(INT64_MAX - 0x7ff)) {
1581 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1582 goto Done;
1583 }
1584 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001585 pDecodedItem->val.epochDate.fSecondsFraction =
1586 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001587 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001588#else
1589 /* Disabling float support causes a floating point
1590 data to error in the default below. The above code
1591 requires floating point conversion to integers and
1592 comparison which requires either floating point HW
1593 or a SW library. */
Laurence Lundblade9682a532020-06-06 18:33:04 -07001594 nReturn = QCBOR_ERR_FLOAT_DATE_UNSUPPORTED;
1595#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001596 break;
1597
Laurence Lundblade9682a532020-06-06 18:33:04 -07001598
Laurence Lundblade59289e52019-12-30 13:44:37 -08001599 default:
1600 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1601 goto Done;
1602 }
1603 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1604
1605Done:
1606 return nReturn;
1607}
1608
1609
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001610/*
1611 Mostly just assign the right data type for the bignum.
1612 */
1613inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1614{
1615 // Stack Use: UsefulBuf 1 -- 16
1616 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1617 return QCBOR_ERR_BAD_OPT_TAG;
1618 }
1619 const UsefulBufC Temp = pDecodedItem->val.string;
1620 pDecodedItem->val.bigNum = Temp;
1621 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1622 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1623 : QCBOR_TYPE_NEGBIGNUM);
1624 return QCBOR_SUCCESS;
1625}
1626
1627
Laurence Lundblade59289e52019-12-30 13:44:37 -08001628#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1629/*
1630 Decode decimal fractions and big floats.
1631
1632 When called pDecodedItem must be the array that is tagged as a big
1633 float or decimal fraction, the array that has the two members, the
1634 exponent and mantissa.
1635
1636 This will fetch and decode the exponent and mantissa and put the
1637 result back into pDecodedItem.
1638 */
1639inline static QCBORError
1640QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1641{
1642 QCBORError nReturn;
1643
1644 // --- Make sure it is an array; track nesting level of members ---
1645 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1646 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1647 goto Done;
1648 }
1649
1650 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001651 // definite length arrays, but not for indefnite. Instead remember
1652 // the nesting level the two integers must be at, which is one
1653 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001654 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1655
1656 // --- Is it a decimal fraction or a bigfloat? ---
1657 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1658 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1659
1660 // --- Get the exponent ---
1661 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001662 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001663 if(nReturn != QCBOR_SUCCESS) {
1664 goto Done;
1665 }
1666 if(exponentItem.uNestingLevel != nNestLevel) {
1667 // Array is empty or a map/array encountered when expecting an int
1668 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1669 goto Done;
1670 }
1671 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1672 // Data arriving as an unsigned int < INT64_MAX has been converted
1673 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1674 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1675 // will be too large for this to handle and thus an error that will
1676 // get handled in the next else.
1677 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1678 } else {
1679 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1680 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1681 goto Done;
1682 }
1683
1684 // --- Get the mantissa ---
1685 QCBORItem mantissaItem;
1686 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1687 if(nReturn != QCBOR_SUCCESS) {
1688 goto Done;
1689 }
1690 if(mantissaItem.uNestingLevel != nNestLevel) {
1691 // Mantissa missing or map/array encountered when expecting number
1692 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1693 goto Done;
1694 }
1695 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1696 // Data arriving as an unsigned int < INT64_MAX has been converted
1697 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1698 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1699 // will be too large for this to handle and thus an error that
1700 // will get handled in an else below.
1701 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1702 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1703 // Got a good big num mantissa
1704 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1705 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001706 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1707 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1708 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 } else {
1710 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1711 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1712 goto Done;
1713 }
1714
1715 // --- Check that array only has the two numbers ---
1716 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001717 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001718 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1719 goto Done;
1720 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001721 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001722
1723Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001724 return nReturn;
1725}
1726#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1727
1728
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001729inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1730{
1731 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1732 return QCBOR_ERR_BAD_OPT_TAG;
1733 }
1734 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1735 return QCBOR_SUCCESS;
1736}
1737
1738
1739inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1740{
1741 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1742 return QCBOR_ERR_BAD_OPT_TAG;
1743 }
1744 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1745 return QCBOR_SUCCESS;
1746}
1747
1748
1749inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1750{
1751 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1752 return QCBOR_ERR_BAD_OPT_TAG;
1753 }
1754 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1755 return QCBOR_SUCCESS;
1756}
1757
1758
1759inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1760{
1761 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1762 return QCBOR_ERR_BAD_OPT_TAG;
1763 }
1764 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1765 return QCBOR_SUCCESS;
1766}
1767
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001768
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001769inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1770{
1771 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1772 return QCBOR_ERR_BAD_OPT_TAG;
1773 }
1774 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1775 return QCBOR_SUCCESS;
1776}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001777
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001778
1779inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1780{
1781 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1782 return QCBOR_ERR_BAD_OPT_TAG;
1783 }
1784 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1785 return QCBOR_SUCCESS;
1786}
1787
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001788
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001789inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1790{
1791 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1792 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001793 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001794 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1795 } else {
1796 return QCBOR_ERR_BAD_OPT_TAG;
1797 }
1798 return QCBOR_SUCCESS;
1799}
1800
1801
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001802inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1803{
1804 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1805 return QCBOR_ERR_BAD_OPT_TAG;
1806 }
1807 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1808 return QCBOR_SUCCESS;
1809}
1810
1811
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001815QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001816QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001817{
1818 QCBORError nReturn;
1819
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001820 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001821 if(nReturn != QCBOR_SUCCESS) {
1822 goto Done;
1823 }
1824
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001825 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1826 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001827
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001828 // Many of the functions here only just map a CBOR tag to
1829 // a QCBOR_TYPE for a string and could probably be
1830 // implemented with less object code. This implementation
1831 // of string types takes about 120 bytes of object code
1832 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001833 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001834 nReturn = DecodeDateString(pDecodedItem);
1835 break;
1836
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001837 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001838 nReturn = DecodeDateEpoch(pDecodedItem);
1839 break;
1840
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001841 case CBOR_TAG_POS_BIGNUM:
1842 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001843 nReturn = DecodeBigNum(pDecodedItem);
1844 break;
1845
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001846 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1847 case CBOR_TAG_DECIMAL_FRACTION:
1848 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001849 // For aggregate tagged types, what goes into pTags is only collected
1850 // from the surrounding data item, not the contents, so pTags is not
1851 // passed on here.
1852
1853 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1854 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001855 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001856
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001857 case CBOR_TAG_CBOR:
1858 nReturn = DecodeWrappedCBOR(pDecodedItem);
1859 break;
1860
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001861 case CBOR_TAG_CBOR_SEQUENCE:
1862 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1863 break;
1864
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001865 case CBOR_TAG_URI:
1866 nReturn = DecodeURI(pDecodedItem);
1867 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001868
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001869 case CBOR_TAG_B64URL:
1870 nReturn = DecodeB64URL(pDecodedItem);
1871 break;
1872
1873 case CBOR_TAG_B64:
1874 nReturn = DecodeB64(pDecodedItem);
1875 break;
1876
1877 case CBOR_TAG_MIME:
1878 case CBOR_TAG_BINARY_MIME:
1879 nReturn = DecodeMIME(pDecodedItem);
1880 break;
1881
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001882 case CBOR_TAG_REGEX:
1883 nReturn = DecodeRegex(pDecodedItem);
1884 break;
1885
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001886 case CBOR_TAG_BIN_UUID:
1887 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001888 break;
1889
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001890 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001891 // The end of the tag list or no tags
1892 // Successful exit from the loop.
1893 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001894
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001895 default:
1896 // A tag that is not understood
1897 // A successful exit from the loop
1898 goto Done;
1899
1900 }
1901 if(nReturn != QCBOR_SUCCESS) {
1902 goto Done;
1903 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001904 }
1905
1906Done:
1907 if(nReturn != QCBOR_SUCCESS) {
1908 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1909 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1910 }
1911 return nReturn;
1912}
1913
1914
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001915QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1916{
1917 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1918
1919 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1920
1921 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07001922 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001923
1924 return uErr;
1925}
1926
1927
Laurence Lundblade59289e52019-12-30 13:44:37 -08001928/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001929 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001930 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001931QCBORError
1932QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1933 QCBORItem *pDecodedItem,
1934 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001935{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001936 QCBORError nReturn;
1937
1938 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1939 if(nReturn != QCBOR_SUCCESS) {
1940 return nReturn;
1941 }
1942
1943 if(pTags != NULL) {
1944 pTags->uNumUsed = 0;
1945 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001946 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001947 break;
1948 }
1949 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1950 return QCBOR_ERR_TOO_MANY_TAGS;
1951 }
1952 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1953 pTags->uNumUsed++;
1954 }
1955 }
1956
1957 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001958}
1959
1960
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001961/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301962 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301963 next one down. If a layer has no work to do for a particular item
1964 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001965
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1967 tagged data items, turning them into the local C representation.
1968 For the most simple it is just associating a QCBOR_TYPE with the data. For
1969 the complex ones that an aggregate of data items, there is some further
1970 decoding and a little bit of recursion.
1971
1972 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301973 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301974 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001975 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001976
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301977 - GetNext_MapEntry -- This handles the combining of two
1978 items, the label and the data, that make up a map entry.
1979 It only does work on maps. It combines the label and data
1980 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001981
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1983 tags into bit flags associated with the data item. No actual decoding
1984 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001985
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301987 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301988 string allocater to create contiguous space for the item. It
1989 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001990
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1992 atomic data item has a "major type", an integer "argument" and optionally
1993 some content. For text and byte strings, the content is the bytes
1994 that make up the string. These are the smallest data items that are
1995 considered to be well-formed. The content may also be other data items in
1996 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001997
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001998 Roughly this takes 300 bytes of stack for vars. Need to
1999 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002000
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302001 */
2002
2003
2004/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002005 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002006 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002007bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002008 const QCBORItem *pItem,
2009 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002010{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002011 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002012 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002013 break;
2014 }
2015 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002016 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002017 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002019
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002020 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002021}
2022
2023
2024/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002025 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002026 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002027QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002028{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002029 QCBORError uReturn = me->uLastError;
2030
2031 if(uReturn != QCBOR_SUCCESS) {
2032 goto Done;
2033 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002034
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002035 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002036 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002037 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002038 goto Done;
2039 }
2040
2041 // Error out if not all the bytes are consumed
2042 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002043 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002045
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002046Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302047 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002048 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002049 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002050
Laurence Lundblade085d7952020-07-24 10:26:30 -07002051 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002052}
2053
2054
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002055/*
2056Public function, see header qcbor/qcbor_decode.h file
2057*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002058uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2059 const QCBORItem *pItem,
2060 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002061{
2062 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2063 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002064 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002065 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002066 }
2067}
2068
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002069
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002070/*
2071
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002072Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002073
Laurence Lundbladeee851742020-01-08 08:37:05 -08002074 - Hit end of input before it was expected while decoding type and
2075 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002076
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002077 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002078
Laurence Lundbladeee851742020-01-08 08:37:05 -08002079 - Hit end of input while decoding a text or byte string
2080 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002081
Laurence Lundbladeee851742020-01-08 08:37:05 -08002082 - Encountered conflicting tags -- e.g., an item is tagged both a date
2083 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002084
Laurence Lundbladeee851742020-01-08 08:37:05 -08002085 - Encontered an array or mapp that has too many items
2086 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002087
Laurence Lundbladeee851742020-01-08 08:37:05 -08002088 - Encountered array/map nesting that is too deep
2089 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002090
Laurence Lundbladeee851742020-01-08 08:37:05 -08002091 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2092 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002093
Laurence Lundbladeee851742020-01-08 08:37:05 -08002094 - The type of a map label is not a string or int
2095 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002096
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002097 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002098
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002099 */
2100
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002101
2102
Laurence Lundbladef6531662018-12-04 10:42:22 +09002103
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002104/* ===========================================================================
2105 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002106
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002107 This implements a simple sting allocator for indefinite length
2108 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2109 implements the function type QCBORStringAllocate and allows easy
2110 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002111
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002112 This particular allocator is built-in for convenience. The caller
2113 can implement their own. All of this following code will get
2114 dead-stripped if QCBORDecode_SetMemPool() is not called.
2115
2116 This is a very primitive memory allocator. It does not track
2117 individual allocations, only a high-water mark. A free or
2118 reallocation must be of the last chunk allocated.
2119
2120 The size of the pool and offset to free memory are packed into the
2121 first 8 bytes of the memory pool so we don't have to keep them in
2122 the decode context. Since the address of the pool may not be
2123 aligned, they have to be packed and unpacked as if they were
2124 serialized data of the wire or such.
2125
2126 The sizes packed in are uint32_t to be the same on all CPU types
2127 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002128 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002129
2130
Laurence Lundbladeee851742020-01-08 08:37:05 -08002131static inline int
2132MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002133{
2134 // Use of UsefulInputBuf is overkill, but it is convenient.
2135 UsefulInputBuf UIB;
2136
Laurence Lundbladeee851742020-01-08 08:37:05 -08002137 // Just assume the size here. It was checked during SetUp so
2138 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002139 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2140 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2141 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2142 return UsefulInputBuf_GetError(&UIB);
2143}
2144
2145
Laurence Lundbladeee851742020-01-08 08:37:05 -08002146static inline int
2147MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002148{
2149 // Use of UsefulOutBuf is overkill, but convenient. The
2150 // length check performed here is useful.
2151 UsefulOutBuf UOB;
2152
2153 UsefulOutBuf_Init(&UOB, Pool);
2154 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2155 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2156 return UsefulOutBuf_GetError(&UOB);
2157}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002158
2159
2160/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002161 Internal function for an allocation, reallocation free and destuct.
2162
2163 Having only one function rather than one each per mode saves space in
2164 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002165
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002166 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2167 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002168static UsefulBuf
2169MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002170{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002171 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002172
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002173 uint32_t uPoolSize;
2174 uint32_t uFreeOffset;
2175
2176 if(uNewSize > UINT32_MAX) {
2177 // This allocator is only good up to 4GB. This check should
2178 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2179 goto Done;
2180 }
2181 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2182
2183 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2184 goto Done;
2185 }
2186
2187 if(uNewSize) {
2188 if(pMem) {
2189 // REALLOCATION MODE
2190 // Calculate pointer to the end of the memory pool. It is
2191 // assumed that pPool + uPoolSize won't wrap around by
2192 // assuming the caller won't pass a pool buffer in that is
2193 // not in legitimate memory space.
2194 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2195
2196 // Check that the pointer for reallocation is in the range of the
2197 // pool. This also makes sure that pointer math further down
2198 // doesn't wrap under or over.
2199 if(pMem >= pPool && pMem < pPoolEnd) {
2200 // Offset to start of chunk for reallocation. This won't
2201 // wrap under because of check that pMem >= pPool. Cast
2202 // is safe because the pool is always less than UINT32_MAX
2203 // because of check in QCBORDecode_SetMemPool().
2204 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2205
2206 // Check to see if the allocation will fit. uPoolSize -
2207 // uMemOffset will not wrap under because of check that
2208 // pMem is in the range of the uPoolSize by check above.
2209 if(uNewSize <= uPoolSize - uMemOffset) {
2210 ReturnValue.ptr = pMem;
2211 ReturnValue.len = uNewSize;
2212
2213 // Addition won't wrap around over because uNewSize was
2214 // checked to be sure it is less than the pool size.
2215 uFreeOffset = uMemOffset + uNewSize32;
2216 }
2217 }
2218 } else {
2219 // ALLOCATION MODE
2220 // uPoolSize - uFreeOffset will not underflow because this
2221 // pool implementation makes sure uFreeOffset is always
2222 // smaller than uPoolSize through this check here and
2223 // reallocation case.
2224 if(uNewSize <= uPoolSize - uFreeOffset) {
2225 ReturnValue.len = uNewSize;
2226 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002227 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002228 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002229 }
2230 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002231 if(pMem) {
2232 // FREE MODE
2233 // Cast is safe because of limit on pool size in
2234 // QCBORDecode_SetMemPool()
2235 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2236 } else {
2237 // DESTRUCT MODE
2238 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002239 }
2240 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002241
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002242 UsefulBuf Pool = {pPool, uPoolSize};
2243 MemPool_Pack(Pool, uFreeOffset);
2244
2245Done:
2246 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002247}
2248
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002249
Laurence Lundbladef6531662018-12-04 10:42:22 +09002250/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002251 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002252 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002253QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2254 UsefulBuf Pool,
2255 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002256{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002257 // The pool size and free mem offset are packed into the beginning
2258 // of the pool memory. This compile time check make sure the
2259 // constant in the header is correct. This check should optimize
2260 // down to nothing.
2261 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002262 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002264
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002265 // The pool size and free offset packed in to the beginning of pool
2266 // memory are only 32-bits. This check will optimize out on 32-bit
2267 // machines.
2268 if(Pool.len > UINT32_MAX) {
2269 return QCBOR_ERR_BUFFER_TOO_LARGE;
2270 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002272 // This checks that the pool buffer given is big enough.
2273 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2274 return QCBOR_ERR_BUFFER_TOO_SMALL;
2275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002276
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002277 pMe->StringAllocator.pfAllocator = MemPool_Function;
2278 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2279 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002280
Laurence Lundblade30816f22018-11-10 13:40:22 +07002281 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002282}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002283
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002284
2285
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002286
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002287
2288
2289/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002290 Consume an entire map or array (and do next to
2291 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002292 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002293static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002294ConsumeItem(QCBORDecodeContext *pMe,
2295 const QCBORItem *pItemToConsume,
2296 uint_fast8_t *puNextNestLevel)
2297{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002298 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002299 QCBORItem Item;
2300
Laurence Lundblade02625d42020-06-25 14:41:41 -07002301 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002302
Laurence Lundblade02625d42020-06-25 14:41:41 -07002303 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002304 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002305
Laurence Lundblade1341c592020-04-11 14:19:05 -07002306 /* This works for definite and indefinite length
2307 * maps and arrays by using the nesting level
2308 */
2309 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002310 uReturn = QCBORDecode_GetNext(pMe, &Item);
2311 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002312 goto Done;
2313 }
2314 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002315
Laurence Lundblade1341c592020-04-11 14:19:05 -07002316 if(puNextNestLevel != NULL) {
2317 *puNextNestLevel = Item.uNextNestLevel;
2318 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002319 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002320
Laurence Lundblade1341c592020-04-11 14:19:05 -07002321 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002322 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002323 if(puNextNestLevel != NULL) {
2324 /* Just pass the nesting level through */
2325 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2326 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002327 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002328 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002329
2330Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002331 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002332}
2333
2334
Laurence Lundblade1341c592020-04-11 14:19:05 -07002335/* Return true if the labels in Item1 and Item2 are the same.
2336 Works only for integer and string labels. Returns false
2337 for any other type. */
2338static inline bool
2339MatchLabel(QCBORItem Item1, QCBORItem Item2)
2340{
2341 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2342 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2343 return true;
2344 }
2345 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002346 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002347 return true;
2348 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002349 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002350 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2351 return true;
2352 }
2353 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2354 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2355 return true;
2356 }
2357 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002358
Laurence Lundblade1341c592020-04-11 14:19:05 -07002359 /* Other label types are never matched */
2360 return false;
2361}
2362
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002363
2364/*
2365 Returns true if Item1 and Item2 are the same type
2366 or if either are of QCBOR_TYPE_ANY.
2367 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002368static inline bool
2369MatchType(QCBORItem Item1, QCBORItem Item2)
2370{
2371 if(Item1.uDataType == Item2.uDataType) {
2372 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002373 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002374 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002375 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002376 return true;
2377 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002378 return false;
2379}
2380
2381
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002382/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002383 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002384
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002385 @param[in] pMe The decode context to search.
2386 @param[in,out] pItemArray The items to search for and the items found.
2387 @param[out] puOffset Byte offset of last item matched.
2388 @param[in] pCBContext Context for the not-found item call back.
2389 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390
2391 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2392
2393 @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.
2394
2395 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2396
2397 @retval Also errors returned by QCBORDecode_GetNext().
2398
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002399 On input pItemArray contains a list of labels and data types
2400 of items to be found.
2401
2402 On output the fully retrieved items are filled in with
2403 values and such. The label was matched, so it never changes.
2404
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002405 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002406 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002407static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002408MapSearch(QCBORDecodeContext *pMe,
2409 QCBORItem *pItemArray,
2410 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002411 void *pCBContext,
2412 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002413{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002414 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002415 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002416
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002417 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002418 uReturn = pMe->uLastError;
2419 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002420 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002421
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002422 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002423 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2424 /* QCBOR_TYPE_NONE as first item indicates just looking
2425 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002426 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2427 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002428 }
2429
Laurence Lundblade085d7952020-07-24 10:26:30 -07002430 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2431 // It is an empty bounded array or map
2432 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2433 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002434 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002435 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002436 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002437 // Nothing is ever found in an empty array or map. All items
2438 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002439 uReturn = QCBOR_SUCCESS;
2440 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002441 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002442 }
2443
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002444 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002445 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2446
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002447 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002448 UsefulInputBuf_Seek(&(pMe->InBuf),
2449 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002450
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002451 /*
2452 Loop over all the items in the map. They could be
2453 deeply nested and this should handle both definite
2454 and indefinite length maps and arrays, so this
2455 adds some complexity.
2456 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002457 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002458 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002459 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002460 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002461 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002463 /* Get the item */
2464 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002465 uReturn = QCBORDecode_GetNext(pMe, &Item);
2466 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002467 /* Got non-well-formed CBOR */
2468 goto Done;
2469 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002470
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002471 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002472 bool bMatched = false;
2473 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2474 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002475 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002476 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2477 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002480 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002481 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002482 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002483 goto Done;
2484 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002485
Laurence Lundblade1341c592020-04-11 14:19:05 -07002486 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002487 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002488 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002489 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002490 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002492 bMatched = true;
2493 }
2494 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002495
2496
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002497 if(!bMatched && pfCallback != NULL) {
2498 /*
2499 Call the callback on unmatched labels.
2500 (It is tempting to do duplicate detection here, but that would
2501 require dynamic memory allocation because the number of labels
2502 that might be encountered is unbounded.)
2503 */
2504 uReturn = (*pfCallback)(pCBContext, &Item);
2505 if(uReturn != QCBOR_SUCCESS) {
2506 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 }
2508 }
2509
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002510 /*
2511 Consume the item whether matched or not. This
2512 does the work of traversing maps and array and
2513 everything in them. In this loop only the
2514 items at the current nesting level are examined
2515 to match the labels.
2516 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002517 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2518 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002519 goto Done;
2520 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002521
2522 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002523
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002524 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002525
2526 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002527 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2528 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002529
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002530 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002531 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2532
2533 Done2:
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002534 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2535 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002536 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002537 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002538 }
2539 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002540
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002541 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002542}
2543
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002544
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002545/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002546 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002547*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002548void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2549 int64_t nLabel,
2550 uint8_t uQcborType,
2551 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002552{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002553 if(pMe->uLastError != QCBOR_SUCCESS) {
2554 return;
2555 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002556
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002557 QCBORItem OneItemSeach[2];
2558 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2559 OneItemSeach[0].label.int64 = nLabel;
2560 OneItemSeach[0].uDataType = uQcborType;
2561 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002562
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002563 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2564 if(uReturn != QCBOR_SUCCESS) {
2565 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002566 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002567 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002568 uReturn = QCBOR_ERR_NOT_FOUND;
2569 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002570 }
2571
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002572 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002573
2574 Done:
2575 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002576}
2577
2578
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002579/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002580 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002581*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002582void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2583 const char *szLabel,
2584 uint8_t uQcborType,
2585 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002586{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002587 if(pMe->uLastError != QCBOR_SUCCESS) {
2588 return;
2589 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002590
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002591 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002592 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2593 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2594 OneItemSeach[0].uDataType = uQcborType;
2595 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002596
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002597 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2598 if(uReturn != QCBOR_SUCCESS) {
2599 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002600 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002601 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002602 uReturn = QCBOR_ERR_NOT_FOUND;
2603 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002604 }
2605
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002606 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002607
2608Done:
2609 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002610}
2611
2612
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002613
2614static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2615{
2616 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2617 if(uDataType == puTypeList[i]) {
2618 return QCBOR_SUCCESS;
2619 }
2620 }
2621 return QCBOR_ERR_UNEXPECTED_TYPE;
2622}
2623
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002624
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002625/**
2626 @param[in] TagSpec Specification for matching tags.
2627 @param[in] uDataType A QCBOR data type
2628
2629 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2630 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2631
2632 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2633 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002634static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002635{
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002636 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002637 // Must match the tag and only the tag
2638 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002639 }
2640
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002641 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2642 if(uReturn == QCBOR_SUCCESS) {
2643 return QCBOR_SUCCESS;
2644 }
2645
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002646 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002647 /* Must match the content type and only the content type.
2648 There was no match just above so it is a fail. */
2649 return QCBOR_ERR_UNEXPECTED_TYPE;
2650 }
2651
2652 /* If here it can match either the tag or the content
2653 and it hasn't matched the content, so the end
2654 result is whether it matches the tag. This is
2655 also the case that the CBOR standard discourages. */
2656
2657 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002658}
2659
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002660
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002661// Semi-private
2662// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002663void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2664 int64_t nLabel,
2665 TagSpecification TagSpec,
2666 QCBORItem *pItem)
2667{
2668 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2669 if(pMe->uLastError != QCBOR_SUCCESS) {
2670 return;
2671 }
2672
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002673 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002674}
2675
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002676// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002677void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2678 const char *szLabel,
2679 TagSpecification TagSpec,
2680 QCBORItem *pItem)
2681{
2682 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2683 if(pMe->uLastError != QCBOR_SUCCESS) {
2684 return;
2685 }
2686
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002687 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002688}
2689
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002690// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002691void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2692 int64_t nLabel,
2693 TagSpecification TagSpec,
2694 UsefulBufC *pString)
2695{
2696 QCBORItem Item;
2697 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2698 if(pMe->uLastError == QCBOR_SUCCESS) {
2699 *pString = Item.val.string;
2700 }
2701}
2702
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002703// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002704void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2705 const char * szLabel,
2706 TagSpecification TagSpec,
2707 UsefulBufC *pString)
2708{
2709 QCBORItem Item;
2710 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2711 if(pMe->uLastError == QCBOR_SUCCESS) {
2712 *pString = Item.val.string;
2713 }
2714}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002716/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002717 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002718*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002719QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2720{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002721 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002722}
2723
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002724/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002725 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002726*/
2727QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2728 QCBORItem *pItemList,
2729 void *pCallbackCtx,
2730 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002731{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002732 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002733}
2734
2735
Laurence Lundblade34691b92020-05-18 22:25:25 -07002736static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002737{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002738 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002739 if(pMe->uLastError != QCBOR_SUCCESS) {
2740 // Already in error state; do nothing.
2741 return;
2742 }
2743
2744 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002745 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002746 if(pMe->uLastError != QCBOR_SUCCESS) {
2747 return;
2748 }
2749
Laurence Lundblade085d7952020-07-24 10:26:30 -07002750 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2751 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2752 return;
2753 }
2754
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002755 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002756 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002757
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002758 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002759 be at the right place.
2760
2761 The UsefulInBuf offset could be anywhere, so no assumption is
2762 made about it.
2763
2764 No assumption is made about the pre-order nesting level either.
2765
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002766 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002767 the map level that is being entered.
2768 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002769 /* Seek to the data item that is the map or array */
2770 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002771
2772 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002773
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002774 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775}
2776
2777
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002778/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002779 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002780*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002781void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002782{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002783 QCBORItem OneItemSeach[2];
2784 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2785 OneItemSeach[0].label.int64 = nLabel;
2786 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2787 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002788
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002789 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002790 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002791}
2792
2793
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002794/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002795 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002796*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002797void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002798{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002799 QCBORItem OneItemSeach[2];
2800 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2801 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2802 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2803 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002804
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002805 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002806}
2807
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002808/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002809 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002810*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002811void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002812{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002813 QCBORItem OneItemSeach[2];
2814 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2815 OneItemSeach[0].label.int64 = nLabel;
2816 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2817 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002818
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002819 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002820}
2821
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002822/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002823 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002824*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002825void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2826{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002827 QCBORItem OneItemSeach[2];
2828 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2829 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2830 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2831 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002832
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002833 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002834}
2835
2836
Laurence Lundblade02625d42020-06-25 14:41:41 -07002837// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002838void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002839{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002840 QCBORError uErr;
2841
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002842 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002843 if(pMe->uLastError != QCBOR_SUCCESS) {
2844 // Already in error state; do nothing.
2845 return;
2846 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002847
2848 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002849 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002850 uErr = QCBORDecode_GetNext(pMe, &Item);
2851 if(uErr != QCBOR_SUCCESS) {
2852 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002853 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002854 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002855 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2856 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002857 }
2858
Laurence Lundbladef0499502020-08-01 11:55:57 -07002859 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002860 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002861 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2862 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002863 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002864 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2865 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002866 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2867 DecodeNesting_Descend(&(pMe->nesting), uType);
2868 }
2869
Laurence Lundblade02625d42020-06-25 14:41:41 -07002870 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002871
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002872 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2873 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002874
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002875Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002876 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002877}
2878
Laurence Lundblade02625d42020-06-25 14:41:41 -07002879
2880/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002881 This is the common work for exiting a level that is a bounded map, array or bstr
2882 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002883
2884 One chunk of work is to set up the pre-order traversal so it is at
2885 the item just after the bounded map, array or bstr that is being
2886 exited. This is somewhat complex.
2887
2888 The other work is to level-up the bounded mode to next higest bounded
2889 mode or the top level if there isn't one.
2890 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002891static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002892ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002893{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002894 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002895
Laurence Lundblade02625d42020-06-25 14:41:41 -07002896 /*
2897 First the pre-order-traversal byte offset is positioned to the
2898 item just after the bounded mode item that was just consumed.
2899 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002900 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2901
Laurence Lundblade02625d42020-06-25 14:41:41 -07002902 /*
2903 Next, set the current nesting level to one above the bounded level
2904 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002905
Laurence Lundblade02625d42020-06-25 14:41:41 -07002906 DecodeNesting_CheckBoundedType() is always called before this and
2907 makes sure pCurrentBounded is valid.
2908 */
2909 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2910
2911 /*
2912 This does the complex work of leveling up the pre-order traversal
2913 when the end of a map or array or another bounded level is
2914 reached. It may do nothing, or ascend all the way to the top
2915 level.
2916 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002917 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002918 if(uErr != QCBOR_SUCCESS) {
2919 goto Done;
2920 }
2921
Laurence Lundblade02625d42020-06-25 14:41:41 -07002922 /*
2923 This makes the next highest bounded level the current bounded
2924 level. If there is no next highest level, then no bounded mode is
2925 in effect.
2926 */
2927 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002928
Laurence Lundblade02625d42020-06-25 14:41:41 -07002929 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002930
2931Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002932 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002933 return uErr;
2934}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002935
Laurence Lundblade02625d42020-06-25 14:41:41 -07002936
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002937// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002938void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002939{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002940 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002941 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002942 return;
2943 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002944
Laurence Lundblade02625d42020-06-25 14:41:41 -07002945 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002946
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002947 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002948 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2949 goto Done;
2950 }
2951
Laurence Lundblade02625d42020-06-25 14:41:41 -07002952 /*
2953 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002954 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002955 from previous map search, then do a dummy search.
2956 */
2957 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002958 QCBORItem Dummy;
2959 Dummy.uLabelType = QCBOR_TYPE_NONE;
2960 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2961 if(uErr != QCBOR_SUCCESS) {
2962 goto Done;
2963 }
2964 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002965
Laurence Lundblade02625d42020-06-25 14:41:41 -07002966 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002967
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002968Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002969 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002970}
2971
2972
Laurence Lundblade1341c592020-04-11 14:19:05 -07002973
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002974static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002975 const QCBORItem *pItem,
2976 uint8_t uTagRequirement,
2977 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002978{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002979 if(pBstr) {
2980 *pBstr = NULLUsefulBufC;
2981 }
2982
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002983 if(pMe->uLastError != QCBOR_SUCCESS) {
2984 // Already in error state; do nothing.
2985 return pMe->uLastError;
2986 }
2987
2988 QCBORError uError = QCBOR_SUCCESS;
2989
2990 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2991 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2992 goto Done;;
2993 }
2994
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002995 const TagSpecification TagSpec =
2996 {
2997 uTagRequirement,
2998 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2999 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3000 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003001
3002 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
3003 if(uError != QCBOR_SUCCESS) {
3004 goto Done;
3005 }
3006
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003007 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003008 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003009 so the increment in NestLevelAscender called by ExitBoundedLevel()
3010 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003011 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003012 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003013
3014 if(pBstr) {
3015 *pBstr = pItem->val.string;
3016 }
3017
3018 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003019
3020 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003021 // Most of these calls are simple inline accessors so this doesn't
3022 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003023 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003024 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3025 // TODO: test this error condition
3026 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
3027 goto Done;
3028 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003029 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003030 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003031
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003032 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003033 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003034 (uint32_t)uPreviousLength,
3035 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003036Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003037 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003038
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003039 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003040}
3041
3042
Laurence Lundblade02625d42020-06-25 14:41:41 -07003043/*
3044 Public function, see header qcbor/qcbor_decode.h file
3045 */
3046void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003047 uint8_t uTagRequirement,
3048 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003049{
3050 if(pMe->uLastError != QCBOR_SUCCESS) {
3051 // Already in error state; do nothing.
3052 return;
3053 }
3054
3055 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003056 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003057 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3058 if(pMe->uLastError != QCBOR_SUCCESS) {
3059 return;
3060 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003061
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003062 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003063 &Item,
3064 uTagRequirement,
3065 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003066}
3067
3068
Laurence Lundblade02625d42020-06-25 14:41:41 -07003069/*
3070 Public function, see header qcbor/qcbor_decode.h file
3071 */
3072void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003073 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003074 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003075 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003076{
3077 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003078 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003079
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003080 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003081}
3082
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003083
Laurence Lundblade02625d42020-06-25 14:41:41 -07003084/*
3085 Public function, see header qcbor/qcbor_decode.h file
3086 */
3087void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003088 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003089 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003090 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003091{
3092 QCBORItem Item;
3093 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3094
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003095 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003096}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003097
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003098
Laurence Lundblade02625d42020-06-25 14:41:41 -07003099/*
3100 Public function, see header qcbor/qcbor_decode.h file
3101 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003102void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003103{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003104 if(pMe->uLastError != QCBOR_SUCCESS) {
3105 // Already in error state; do nothing.
3106 return;
3107 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003108
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003109 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003110 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3111 return;
3112 }
3113
3114 /*
3115 Reset the length of the UsefulInputBuf to what it was before
3116 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003117 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003118 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3119 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003120
3121
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003123 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003124}
3125
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003126
Laurence Lundbladee6430642020-03-14 21:15:44 -07003127
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003128
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003129
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003130
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003131
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003132
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003133static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3134{
3135 switch(pItem->uDataType) {
3136 case QCBOR_TYPE_TRUE:
3137 *pBool = true;
3138 return QCBOR_SUCCESS;
3139 break;
3140
3141 case QCBOR_TYPE_FALSE:
3142 *pBool = false;
3143 return QCBOR_SUCCESS;
3144 break;
3145
3146 default:
3147 return QCBOR_ERR_UNEXPECTED_TYPE;
3148 break;
3149 }
3150}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003151
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003152
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003153/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003154 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003155*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003156void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003157{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003158 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003159 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003160 return;
3161 }
3162
Laurence Lundbladec4537442020-04-14 18:53:22 -07003163 QCBORError nError;
3164 QCBORItem Item;
3165
3166 nError = QCBORDecode_GetNext(pMe, &Item);
3167 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003168 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003169 return;
3170 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003171 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003172}
3173
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003174
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003175/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003176 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003177*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003178void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003179{
3180 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003181 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003182
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003183 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003184}
3185
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003186
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003187/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003188 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003189*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003190void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3191{
3192 QCBORItem Item;
3193 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3194
3195 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3196}
3197
3198
3199
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003200void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3201 TagSpecification TagSpec,
3202 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003203{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003204 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003205 // Already in error state, do nothing
3206 return;
3207 }
3208
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003209 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003210 QCBORItem Item;
3211
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003212 uError = QCBORDecode_GetNext(pMe, &Item);
3213 if(uError != QCBOR_SUCCESS) {
3214 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003215 return;
3216 }
3217
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003218 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3219
3220 if(pMe->uLastError == QCBOR_SUCCESS) {
3221 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003222 }
3223}
3224
Laurence Lundbladec4537442020-04-14 18:53:22 -07003225
3226
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003227
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003228static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003229 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003230 UsefulBufC *pValue,
3231 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003232{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003233 const TagSpecification TagSpec =
3234 {
3235 uTagRequirement,
3236 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3237 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3238 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003239
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003240 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3241 if(uErr != QCBOR_SUCCESS) {
3242 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003243 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003244
3245 *pValue = pItem->val.string;
3246
3247 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3248 *pbIsNegative = false;
3249 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3250 *pbIsNegative = true;
3251 }
3252
3253 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003254}
3255
3256
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003257/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003258 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003259 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003260void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3261 uint8_t uTagRequirement,
3262 UsefulBufC *pValue,
3263 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003264{
3265 if(pMe->uLastError != QCBOR_SUCCESS) {
3266 // Already in error state, do nothing
3267 return;
3268 }
3269
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003270 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003271 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3272 if(uError != QCBOR_SUCCESS) {
3273 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003274 return;
3275 }
3276
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003277 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003278}
3279
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003280
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003281/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003282 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003283*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003284void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3285 int64_t nLabel,
3286 uint8_t uTagRequirement,
3287 UsefulBufC *pValue,
3288 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003289{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003290 QCBORItem Item;
3291 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003292 if(pMe->uLastError != QCBOR_SUCCESS) {
3293 return;
3294 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003295
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003296 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003297}
3298
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003299
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003300/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003301 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003302*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003303void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3304 const char *szLabel,
3305 uint8_t uTagRequirement,
3306 UsefulBufC *pValue,
3307 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003308{
3309 QCBORItem Item;
3310 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003311 if(pMe->uLastError != QCBOR_SUCCESS) {
3312 return;
3313 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003314
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003315 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003316}
3317
3318
3319
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003320
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003321// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003322QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3323 const QCBORItem *pItem,
3324 UsefulBufC *pMessage,
3325 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003326{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003327 const TagSpecification TagSpecText =
3328 {
3329 uTagRequirement,
3330 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3331 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3332 };
3333 const TagSpecification TagSpecBinary =
3334 {
3335 uTagRequirement,
3336 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3337 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3338 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003339
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003340 QCBORError uReturn;
3341
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003342 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003343 *pMessage = pItem->val.string;
3344 if(pbIsNot7Bit != NULL) {
3345 *pbIsNot7Bit = false;
3346 }
3347 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003348 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003349 *pMessage = pItem->val.string;
3350 if(pbIsNot7Bit != NULL) {
3351 *pbIsNot7Bit = true;
3352 }
3353 uReturn = QCBOR_SUCCESS;
3354
3355 } else {
3356 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3357 }
3358
3359 return uReturn;
3360}
3361
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003362// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3363
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003364
3365
3366
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003367#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003368
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003369typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003370
3371
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003373static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003374{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003375 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003376
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003377 if(uResult != 0) {
3378 /* This loop will run a maximum of 19 times because
3379 * UINT64_MAX < 10 ^^ 19. More than that will cause
3380 * exit with the overflow error
3381 */
3382 for(; nExponent > 0; nExponent--) {
3383 if(uResult > UINT64_MAX / 10) {
3384 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3385 }
3386 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003387 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003388
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003389 for(; nExponent < 0; nExponent++) {
3390 uResult = uResult / 10;
3391 if(uResult == 0) {
3392 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3393 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003394 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003395 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003396 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003397
3398 *puResult = uResult;
3399
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003400 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003401}
3402
3403
Laurence Lundbladee6430642020-03-14 21:15:44 -07003404/* Convert a decimal fraction to an int64_t without using
3405 floating point or math libraries. Most decimal fractions
3406 will not fit in an int64_t and this will error out with
3407 under or overflow
3408 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003409static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003410{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003411 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003412
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003413 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003414
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003415 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003416 * INT64_MAX < 2^31. More than that will cause
3417 * exist with the overflow error
3418 */
3419 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003420 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003421 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003422 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003423 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003424 nExponent--;
3425 }
3426
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003427 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003428 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3430 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003431 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003432 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003433 }
3434
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003435 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003436
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003437 return QCBOR_SUCCESS;
3438}
3439
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003440/*
3441 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3442 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003443static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3444{
3445 uint64_t uResult;
3446
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003447 // Take the absolute value of the mantissa and convert to unsigned.
3448 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003449 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3450
3451 // Do the exponentiation of the positive mantissa
3452 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3453 if(uReturn) {
3454 return uReturn;
3455 }
3456
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003457
Laurence Lundblade983500d2020-05-14 11:49:34 -07003458 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3459 of INT64_MIN. This assumes two's compliment representation where
3460 INT64_MIN is one increment farther from 0 than INT64_MAX.
3461 Trying to write -INT64_MIN doesn't work to get this because the
3462 compiler tries to work with an int64_t which can't represent
3463 -INT64_MIN.
3464 */
3465 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3466
3467 // Error out if too large
3468 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003469 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3470 }
3471
3472 // Casts are safe because of checks above
3473 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3474
3475 return QCBOR_SUCCESS;
3476}
3477
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003478/*
3479 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3480 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003481static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3482{
3483 if(nMantissa < 0) {
3484 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3485 }
3486
3487 // Cast to unsigned is OK because of check for negative
3488 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3489 // Exponentiation is straight forward
3490 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3491}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003492#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3493
3494
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003495
3496
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003497#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003498
3499
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003500static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003501{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003502 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003503
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003504 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003505 const uint8_t *pByte = BigNum.ptr;
3506 size_t uLen = BigNum.len;
3507 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003508 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003509 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003510 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003511 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003512 }
3513
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003514 *pResult = uResult;
3515 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003516}
3517
Laurence Lundblade887add82020-05-17 05:50:34 -07003518static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003519{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003520 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003521}
3522
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003523static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003524{
3525 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003526 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3527 if(uError) {
3528 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003529 }
3530 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3531 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003532 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003533}
3534
3535
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003536static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003537{
3538 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003539 /* negaative int furthest from zero is INT64_MIN
3540 which is expressed as -INT64_MAX-1. The value of
3541 a negative bignum is -n-1, one further from zero
3542 than the positive bignum */
3543
3544 /* say INT64_MIN is -2; then INT64_MAX is 1.
3545 Then -n-1 <= INT64_MIN.
3546 Then -n -1 <= -INT64_MAX - 1
3547 THen n <= INT64_MAX. */
3548 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003549 if(uError) {
3550 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003551 }
3552 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003553 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003554 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003555 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003556 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003557}
3558
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003559
3560static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
3561{
3562 while((uInt & 0xff00000000000000UL) == 0) {
3563 uInt = uInt << 8;
3564 };
3565
3566 UsefulOutBuf UOB;
3567
3568 UsefulOutBuf_Init(&UOB, Buffer);
3569
3570 while(uInt) {
3571 const uint64_t xx = uInt & 0xff00000000000000UL;
3572 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
3573 uInt = uInt << 8;
3574 (void)xx;
3575 }
3576
3577 return UsefulOutBuf_OutUBuf(&UOB);
3578}
3579
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003580#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003581
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003582
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003583/*
3584Convert a integers and floats to an int64_t.
3585
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003586\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003587
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003588\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003589
3590\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3591
3592\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3593
3594*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003595static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003596{
3597 switch(pItem->uDataType) {
3598 // TODO: float when ifdefs are set
3599 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003600 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601 // TODO: what about under/overflow here?
3602 // Invokes the floating-point HW and/or compiler-added libraries
3603 feclearexcept(FE_ALL_EXCEPT);
3604 *pnValue = llround(pItem->val.dfnum);
3605 if(fetestexcept(FE_INVALID)) {
3606 // TODO: better error code
3607 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3608 }
3609 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003610 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003611 }
3612 break;
3613
3614 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003615 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003616 *pnValue = pItem->val.int64;
3617 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003618 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003619 }
3620 break;
3621
3622 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003623 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003624 if(pItem->val.uint64 < INT64_MAX) {
3625 *pnValue = pItem->val.int64;
3626 } else {
3627 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3628 }
3629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631 }
3632 break;
3633
3634 default:
3635 return QCBOR_ERR_UNEXPECTED_TYPE;
3636 }
3637 return QCBOR_SUCCESS;
3638}
3639
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003640
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003641void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003642 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003643 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003644 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003645{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003646 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647 return;
3648 }
3649
Laurence Lundbladee6430642020-03-14 21:15:44 -07003650 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003651 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3652 if(uError) {
3653 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003654 return;
3655 }
3656
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003657 if(pItem) {
3658 *pItem = Item;
3659 }
3660
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003661 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003662}
3663
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003664
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003665void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3666 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003667 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003668 int64_t *pnValue,
3669 QCBORItem *pItem)
3670{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003671 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003672 if(pMe->uLastError != QCBOR_SUCCESS) {
3673 return;
3674 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003675
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003676 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003677}
3678
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003679
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003680void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3681 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003682 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003683 int64_t *pnValue,
3684 QCBORItem *pItem)
3685{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003686 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003687 if(pMe->uLastError != QCBOR_SUCCESS) {
3688 return;
3689 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003690
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003691 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003692}
3693
3694
3695
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003696/*
3697 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003698
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003699 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003700
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003701 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003702
3703 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3704
3705 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3706
3707 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003708static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003709{
3710 QCBORError uErr;
3711
3712 switch(pItem->uDataType) {
3713
3714 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003715 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003716 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003717 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003718 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003719 }
3720 break;
3721
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003722 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003723 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003724 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003725 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003726 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727 }
3728 break;
3729
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003730#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3731 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003732 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003733 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3734 pItem->val.expAndMantissa.nExponent,
3735 pnValue,
3736 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003738 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003739 }
3740 break;
3741
3742 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003743 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003744 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3745 pItem->val.expAndMantissa.nExponent,
3746 pnValue,
3747 Exponentitate2);
3748 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003749 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003750 }
3751 break;
3752
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003753 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003754 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003755 int64_t nMantissa;
3756 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3757 if(uErr) {
3758 return uErr;
3759 }
3760 return ExponentiateNN(nMantissa,
3761 pItem->val.expAndMantissa.nExponent,
3762 pnValue,
3763 Exponentitate10);
3764 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003765 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003766 }
3767 break;
3768
3769 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003770 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003771 int64_t nMantissa;
3772 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3773 if(uErr) {
3774 return uErr;
3775 }
3776 return ExponentiateNN(nMantissa,
3777 pItem->val.expAndMantissa.nExponent,
3778 pnValue,
3779 Exponentitate10);
3780 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003781 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003782 }
3783 break;
3784
3785 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003786 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003787 int64_t nMantissa;
3788 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3789 if(uErr) {
3790 return uErr;
3791 }
3792 return ExponentiateNN(nMantissa,
3793 pItem->val.expAndMantissa.nExponent,
3794 pnValue,
3795 Exponentitate2);
3796 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003797 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003798 }
3799 break;
3800
3801 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003802 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003803 int64_t nMantissa;
3804 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 Exponentitate2);
3812 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003813 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003814 }
3815 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003816#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3817
Laurence Lundbladee6430642020-03-14 21:15:44 -07003818
Laurence Lundbladec4537442020-04-14 18:53:22 -07003819 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003820 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003821}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003822
3823
Laurence Lundbladec4537442020-04-14 18:53:22 -07003824/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003825 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003826 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003827void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003828{
3829 QCBORItem Item;
3830
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003831 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003832
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003833 if(pMe->uLastError == QCBOR_SUCCESS) {
3834 // The above conversion succeeded
3835 return;
3836 }
3837
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003838 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003840 return;
3841 }
3842
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003843 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003844}
3845
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003846
3847/*
3848Public function, see header qcbor/qcbor_decode.h file
3849*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003850void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003851{
3852 QCBORItem Item;
3853
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003854 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003855
3856 if(pMe->uLastError == QCBOR_SUCCESS) {
3857 // The above conversion succeeded
3858 return;
3859 }
3860
3861 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3862 // The above conversion failed in a way that code below can't correct
3863 return;
3864 }
3865
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003866 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003867}
3868
3869
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003870/*
3871Public function, see header qcbor/qcbor_decode.h file
3872*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003873void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003874{
3875 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003876 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003877
3878 if(pMe->uLastError == QCBOR_SUCCESS) {
3879 // The above conversion succeeded
3880 return;
3881 }
3882
3883 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3884 // The above conversion failed in a way that code below can't correct
3885 return;
3886 }
3887
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003888 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003889}
3890
3891
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003892static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003893{
3894 switch(pItem->uDataType) {
3895 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003896 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003897 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003898 feclearexcept(FE_ALL_EXCEPT);
3899 double dRounded = round(pItem->val.dfnum);
3900 // TODO: over/underflow
3901 if(fetestexcept(FE_INVALID)) {
3902 // TODO: better error code
3903 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3904 } else if(isnan(dRounded)) {
3905 // TODO: better error code
3906 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3907 } else if(dRounded >= 0) {
3908 *puValue = (uint64_t)dRounded;
3909 } else {
3910 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3911 }
3912 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003913 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003914 }
3915 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003916
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003917 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003918 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003919 if(pItem->val.int64 >= 0) {
3920 *puValue = (uint64_t)pItem->val.int64;
3921 } else {
3922 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3923 }
3924 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003925 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003926 }
3927 break;
3928
3929 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003930 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003931 *puValue = pItem->val.uint64;
3932 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003933 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003934 }
3935 break;
3936
3937 default:
3938 return QCBOR_ERR_UNEXPECTED_TYPE;
3939 }
3940 return QCBOR_SUCCESS;
3941}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003942
3943
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003944void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003945 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003946 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003947 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003949 if(pMe->uLastError != QCBOR_SUCCESS) {
3950 return;
3951 }
3952
Laurence Lundbladec4537442020-04-14 18:53:22 -07003953 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003954
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003955 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3956 if(uError) {
3957 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003958 return;
3959 }
3960
Laurence Lundbladea826c502020-05-10 21:07:00 -07003961 if(pItem) {
3962 *pItem = Item;
3963 }
3964
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003965 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003966}
3967
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003968
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003969
3970
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003971void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3972 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003973 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974 uint64_t *puValue,
3975 QCBORItem *pItem)
3976{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003977 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003978 if(pMe->uLastError != QCBOR_SUCCESS) {
3979 return;
3980 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003981
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003983}
3984
3985
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003986void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003987 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003988 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003989 uint64_t *puValue,
3990 QCBORItem *pItem)
3991{
3992 if(pMe->uLastError != QCBOR_SUCCESS) {
3993 return;
3994 }
3995
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003996 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003997 if(pMe->uLastError != QCBOR_SUCCESS) {
3998 return;
3999 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004000
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004001 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004002}
4003
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004004/*
4005 Public function, see header qcbor/qcbor_decode.h file
4006*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004008{
4009 QCBORError uErr;
4010
4011 switch(pItem->uDataType) {
4012
4013 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004014 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004015 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4016 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004018 }
4019 break;
4020
4021 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004023 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4024 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004025 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004026 }
4027 break;
4028
4029#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4030
4031 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004032 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004033 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4034 pItem->val.expAndMantissa.nExponent,
4035 puValue,
4036 Exponentitate10);
4037 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004039 }
4040 break;
4041
4042 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004043 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4045 pItem->val.expAndMantissa.nExponent,
4046 puValue,
4047 Exponentitate2);
4048 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004049 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004050 }
4051 break;
4052
4053 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004055 // TODO: Would be better to convert to unsigned
4056 int64_t nMantissa;
4057 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4058 if(uErr != QCBOR_SUCCESS) {
4059 return uErr;
4060 }
4061 return ExponentitateNU(nMantissa,
4062 pItem->val.expAndMantissa.nExponent,
4063 puValue,
4064 Exponentitate10);
4065 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004066 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004067 }
4068 break;
4069
4070 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004072 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4073 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004074 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004075 }
4076 break;
4077
4078 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004079 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004080 // TODO: Would be better to convert to unsigned
4081 int64_t nMantissa;
4082 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4083 if(uErr != QCBOR_SUCCESS) {
4084 return uErr;
4085 }
4086 return ExponentitateNU(nMantissa,
4087 pItem->val.expAndMantissa.nExponent,
4088 puValue,
4089 Exponentitate2);
4090 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004091 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004092 }
4093 break;
4094
4095 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004096 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004097 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4098 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004099 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004100 }
4101 break;
4102#endif
4103 default:
4104 return QCBOR_ERR_UNEXPECTED_TYPE;
4105 }
4106}
4107
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004108/*
4109 Public function, see header qcbor/qcbor_decode.h file
4110*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004112{
4113 QCBORItem Item;
4114
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004116
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004117 if(pMe->uLastError == QCBOR_SUCCESS) {
4118 // The above conversion succeeded
4119 return;
4120 }
4121
4122 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4123 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004124 return;
4125 }
4126
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004128}
4129
Laurence Lundbladec4537442020-04-14 18:53:22 -07004130
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004131/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004132 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004133*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004134void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004135{
4136 QCBORItem Item;
4137
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004138 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004139
4140 if(pMe->uLastError == QCBOR_SUCCESS) {
4141 // The above conversion succeeded
4142 return;
4143 }
4144
4145 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4146 // The above conversion failed in a way that code below can't correct
4147 return;
4148 }
4149
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004151}
4152
4153
4154/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004155 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004156*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004157void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004158{
4159 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004161
4162 if(pMe->uLastError == QCBOR_SUCCESS) {
4163 // The above conversion succeeded
4164 return;
4165 }
4166
4167 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4168 // The above conversion failed in a way that code below can't correct
4169 return;
4170 }
4171
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004172 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004173}
4174
4175
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177{
4178 switch(pItem->uDataType) {
4179 // TODO: float when ifdefs are set
4180 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4182 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004183 *pdValue = pItem->val.dfnum;
4184 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004185 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004186 }
4187 }
4188 break;
4189
4190 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004191 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004192 // TODO: how does this work?
4193 *pdValue = (double)pItem->val.int64;
4194
4195 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004196 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004197 }
4198 break;
4199
4200 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004201 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004202 *pdValue = (double)pItem->val.uint64;
4203 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004205 }
4206 break;
4207
4208 default:
4209 return QCBOR_ERR_UNEXPECTED_TYPE;
4210 }
4211
4212 return QCBOR_SUCCESS;
4213}
4214
4215
4216
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004217void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004218 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004219 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004220 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004221{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004222 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004223 return;
4224 }
4225
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004226 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004227
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004228 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004229 if(uError) {
4230 pMe->uLastError = (uint8_t)uError;
4231 return;
4232 }
4233
4234 if(pItem) {
4235 *pItem = Item;
4236 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004237
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004239}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004240
Laurence Lundbladec4537442020-04-14 18:53:22 -07004241
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004242void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4243 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004244 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004245 double *pdValue,
4246 QCBORItem *pItem)
4247{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004248 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004249 if(pMe->uLastError != QCBOR_SUCCESS) {
4250 return;
4251 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004252
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004253 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004254}
4255
4256void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4257 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004258 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004259 double *pdValue,
4260 QCBORItem *pItem)
4261{
4262 if(pMe->uLastError != QCBOR_SUCCESS) {
4263 return;
4264 }
4265
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004266 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004267 if(pMe->uLastError != QCBOR_SUCCESS) {
4268 return;
4269 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004270
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004271 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272}
4273
4274
4275
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004276static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4277{
4278 double dResult;
4279
4280 dResult = 0.0;
4281 const uint8_t *pByte = BigNum.ptr;
4282 size_t uLen = BigNum.len;
4283 /* This will overflow and become the float value INFINITY if the number
4284 is too large to fit. No error will be logged.
4285 TODO: should an error be logged? */
4286 while(uLen--) {
4287 dResult = (dResult * 256.0) + (double)*pByte++;
4288 }
4289
4290 return dResult;
4291}
4292
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004293static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004294{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004295 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004296 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4297
4298 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004299 switch(pItem->uDataType) {
4300 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004301
4302#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004303 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004304 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004305 // TODO: rounding and overflow errors
4306 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4307 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4308 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004309 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004310 }
4311 break;
4312
4313 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004314 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004315 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4316 exp2((double)pItem->val.expAndMantissa.nExponent);
4317 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004318 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004319 }
4320 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004321#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
4323 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004324 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004325 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4326 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004327 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004328 }
4329 break;
4330
4331 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004332 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004333 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004334 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004335 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004336 }
4337 break;
4338
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004339#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004340 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004341 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004342 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4343 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4344 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004345 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004346 }
4347 break;
4348
4349 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004350 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004351 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4352 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4353 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004354 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004355 }
4356 break;
4357
4358 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004359 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4361 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4362 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004363 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004364 }
4365 break;
4366
4367 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004368 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004369 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4371 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004372 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004373 }
4374 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004375#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4376
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004377
4378 default:
4379 return QCBOR_ERR_UNEXPECTED_TYPE;
4380 }
4381
4382 return QCBOR_SUCCESS;
4383}
4384
4385
4386/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004387 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004388*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004389void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004390{
4391
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004392 QCBORItem Item;
4393
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004394 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004395
4396 if(pMe->uLastError == QCBOR_SUCCESS) {
4397 // The above conversion succeeded
4398 return;
4399 }
4400
4401 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4402 // The above conversion failed in a way that code below can't correct
4403 return;
4404 }
4405
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004407}
4408
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409
4410/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004411 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004412*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004413void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414{
4415 QCBORItem Item;
4416
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004417 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418
4419 if(pMe->uLastError == QCBOR_SUCCESS) {
4420 // The above conversion succeeded
4421 return;
4422 }
4423
4424 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4425 // The above conversion failed in a way that code below can't correct
4426 return;
4427 }
4428
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004429 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430}
4431
4432
4433/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004434 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437{
4438 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440
4441 if(pMe->uLastError == QCBOR_SUCCESS) {
4442 // The above conversion succeeded
4443 return;
4444 }
4445
4446 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4447 // The above conversion failed in a way that code below can't correct
4448 return;
4449 }
4450
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004453
4454
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004455
4456
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004457#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004458static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4459 TagSpecification TagSpec,
4460 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004461{
4462 QCBORError uErr;
4463 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004464 while(1) {
4465 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4466 if(uErr != QCBOR_SUCCESS) {
4467 goto Done;
4468 }
4469
4470 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4471 break; // Successful exit. Moving on to finish decoding.
4472 }
4473
4474 // The item is an array, which means an undecoded
4475 // mantissa and exponent, so decode it. It will then
4476 // have a different type and exit the loop if.
4477 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4478 if(uErr != QCBOR_SUCCESS) {
4479 goto Done;
4480 }
4481
4482 // Second time around, the type must match.
4483 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
4484 }
4485Done:
4486 return uErr;
4487}
4488
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004489
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004490static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004491 TagSpecification TagSpec,
4492 QCBORItem *pItem,
4493 int64_t *pnMantissa,
4494 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004495{
4496 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004497
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004498 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004499 if(uErr != QCBOR_SUCCESS) {
4500 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004501 }
4502
4503 switch (pItem->uDataType) {
4504
4505 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004506 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004507 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4508 *pnExponent = pItem->val.expAndMantissa.nExponent;
4509 break;
4510
4511 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004512 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004513 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004514 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004515 break;
4516
4517 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004518 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004519 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004520 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004521 break;
4522
4523 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004524 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004525 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004526
4527 Done:
4528 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004529}
4530
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004531
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004532static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004533 TagSpecification TagSpec,
4534 QCBORItem *pItem,
4535 UsefulBuf BufferForMantissa,
4536 UsefulBufC *pMantissa,
4537 bool *pbIsNegative,
4538 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004539{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004540 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004541
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004542 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004543 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004544 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004545 }
4546
4547 uint64_t uMantissa;
4548
4549 switch (pItem->uDataType) {
4550
4551 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004552 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004553 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4554 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4555 *pbIsNegative = false;
4556 } else {
4557 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4558 *pbIsNegative = true;
4559 }
4560 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4561 *pnExponent = pItem->val.expAndMantissa.nExponent;
4562 break;
4563
4564 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004565 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004566 *pnExponent = pItem->val.expAndMantissa.nExponent;
4567 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4568 *pbIsNegative = false;
4569 break;
4570
4571 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004572 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004573 *pnExponent = pItem->val.expAndMantissa.nExponent;
4574 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4575 *pbIsNegative = true;
4576 break;
4577
4578 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004579 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004580 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004581
4582Done:
4583 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004584}
4585
4586
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004587/*
4588 Public function, see header qcbor/qcbor_decode.h file
4589*/
4590void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4591 uint8_t uTagRequirement,
4592 int64_t *pnMantissa,
4593 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004594{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004595 if(pMe->uLastError != QCBOR_SUCCESS) {
4596 return;
4597 }
4598
4599 QCBORItem Item;
4600 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4601 if(uError) {
4602 pMe->uLastError = (uint8_t)uError;
4603 return;
4604 }
4605
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004606 const TagSpecification TagSpec =
4607 {
4608 uTagRequirement,
4609 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4610 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4611 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004612
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004613 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004614}
4615
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004616
4617/*
4618 Public function, see header qcbor/qcbor_decode.h file
4619*/
4620void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004621 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004622 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004623 int64_t *pnMantissa,
4624 int64_t *pnExponent)
4625{
4626 if(pMe->uLastError != QCBOR_SUCCESS) {
4627 return;
4628 }
4629
4630 QCBORItem Item;
4631 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4632
4633 const TagSpecification TagSpec =
4634 {
4635 uTagRequirement,
4636 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4637 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4638 };
4639
4640 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4641}
4642
4643
4644/*
4645 Public function, see header qcbor/qcbor_decode.h file
4646*/
4647void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004648 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004649 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004650 int64_t *pnMantissa,
4651 int64_t *pnExponent)
4652{
4653 if(pMe->uLastError != QCBOR_SUCCESS) {
4654 return;
4655 }
4656
4657 QCBORItem Item;
4658 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4659
4660 const TagSpecification TagSpec =
4661 {
4662 uTagRequirement,
4663 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4664 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4665 };
4666
4667 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4668}
4669
4670
4671/*
4672 Public function, see header qcbor/qcbor_decode.h file
4673*/
4674void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4675 uint8_t uTagRequirement,
4676 UsefulBuf MantissaBuffer,
4677 UsefulBufC *pMantissa,
4678 bool *pbMantissaIsNegative,
4679 int64_t *pnExponent)
4680{
4681 if(pMe->uLastError != QCBOR_SUCCESS) {
4682 return;
4683 }
4684
4685 QCBORItem Item;
4686 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4687 if(uError) {
4688 pMe->uLastError = (uint8_t)uError;
4689 return;
4690 }
4691
4692 const TagSpecification TagSpec =
4693 {
4694 uTagRequirement,
4695 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4696 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4697 };
4698
4699 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4700}
4701
4702
4703/*
4704 Public function, see header qcbor/qcbor_decode.h file
4705*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004706void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004707 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004708 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004709 UsefulBuf BufferForMantissa,
4710 UsefulBufC *pMantissa,
4711 bool *pbIsNegative,
4712 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004713{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004714 if(pMe->uLastError != QCBOR_SUCCESS) {
4715 return;
4716 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004717
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004718 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004719 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004720 if(pMe->uLastError != QCBOR_SUCCESS) {
4721 return;
4722 }
4723
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004724 const TagSpecification TagSpec =
4725 {
4726 uTagRequirement,
4727 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4728 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4729 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004730
4731 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004732}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004733
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004734
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004735/*
4736 Public function, see header qcbor/qcbor_decode.h file
4737*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004738void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004739 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004740 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004741 UsefulBuf BufferForMantissa,
4742 UsefulBufC *pMantissa,
4743 bool *pbIsNegative,
4744 int64_t *pnExponent)
4745{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004746 if(pMe->uLastError != QCBOR_SUCCESS) {
4747 return;
4748 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004749
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004750 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004751 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4752 if(pMe->uLastError != QCBOR_SUCCESS) {
4753 return;
4754 }
4755
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004756 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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004762
4763 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4764}
4765
4766
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004767/*
4768 Public function, see header qcbor/qcbor_decode.h file
4769*/
4770void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
4771 uint8_t uTagRequirement,
4772 int64_t *pnMantissa,
4773 int64_t *pnExponent)
4774{
4775 if(pMe->uLastError != QCBOR_SUCCESS) {
4776 return;
4777 }
4778
4779 QCBORItem Item;
4780 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4781 if(uError) {
4782 pMe->uLastError = (uint8_t)uError;
4783 return;
4784 }
4785 const TagSpecification TagSpec =
4786 {
4787 uTagRequirement,
4788 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4789 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4790 };
4791
4792 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4793}
4794
4795
4796/*
4797 Public function, see header qcbor/qcbor_decode.h file
4798*/
4799void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004800 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004801 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004802 int64_t *pnMantissa,
4803 int64_t *pnExponent)
4804{
4805 if(pMe->uLastError != QCBOR_SUCCESS) {
4806 return;
4807 }
4808
4809 QCBORItem Item;
4810 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4811 if(pMe->uLastError != QCBOR_SUCCESS) {
4812 return;
4813 }
4814
4815 const TagSpecification TagSpec =
4816 {
4817 uTagRequirement,
4818 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4819 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4820 };
4821
4822 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4823}
4824
4825
4826/*
4827 Public function, see header qcbor/qcbor_decode.h file
4828*/
4829void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004830 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004831 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004832 int64_t *pnMantissa,
4833 int64_t *pnExponent)
4834{
4835 if(pMe->uLastError != QCBOR_SUCCESS) {
4836 return;
4837 }
4838
4839 QCBORItem Item;
4840 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4841 if(pMe->uLastError != QCBOR_SUCCESS) {
4842 return;
4843 }
4844
4845 const TagSpecification TagSpec =
4846 {
4847 uTagRequirement,
4848 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4849 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4850 };
4851
4852 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4853}
4854
4855
4856/*
4857 Public function, see header qcbor/qcbor_decode.h file
4858*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004859void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
4860 uint8_t uTagRequirement,
4861 UsefulBuf MantissaBuffer,
4862 UsefulBufC *pMantissa,
4863 bool *pbMantissaIsNegative,
4864 int64_t *pnExponent)
4865{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004866 if(pMe->uLastError != QCBOR_SUCCESS) {
4867 return;
4868 }
4869
4870 QCBORItem Item;
4871 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4872 if(uError) {
4873 pMe->uLastError = (uint8_t)uError;
4874 return;
4875 }
4876
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004877 const TagSpecification TagSpec =
4878 {
4879 uTagRequirement,
4880 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4881 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4882 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004883
4884 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004885}
4886
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004887
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004888/*
4889 Public function, see header qcbor/qcbor_decode.h file
4890*/
4891void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004892 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004893 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004894 UsefulBuf BufferForMantissa,
4895 UsefulBufC *pMantissa,
4896 bool *pbIsNegative,
4897 int64_t *pnExponent)
4898{
4899 if(pMe->uLastError != QCBOR_SUCCESS) {
4900 return;
4901 }
4902
4903 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004904 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4905 if(pMe->uLastError != QCBOR_SUCCESS) {
4906 return;
4907 }
4908
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004909 const TagSpecification TagSpec =
4910 {
4911 uTagRequirement,
4912 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4913 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4914 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004915
4916 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4917}
4918
4919
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004920/*
4921 Public function, see header qcbor/qcbor_decode.h file
4922*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004923void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004924 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004925 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004926 UsefulBuf BufferForMantissa,
4927 UsefulBufC *pMantissa,
4928 bool *pbIsNegative,
4929 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004930{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004931 if(pMe->uLastError != QCBOR_SUCCESS) {
4932 return;
4933 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004934
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004935 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004936 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4937 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004938 return;
4939 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004940
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004941 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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004947
4948 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004949}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004950
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004951#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */