blob: 094a0c16a7d86ba4998660f90262ab01547e27bd [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 Lundblade67bd5512018-11-02 21:44:06 +0700799 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
800 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700801 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700802 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
804 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700805 break;
806 case DOUBLE_PREC_FLOAT:
807 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700808 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700809 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 case CBOR_SIMPLEV_FALSE: // 20
812 case CBOR_SIMPLEV_TRUE: // 21
813 case CBOR_SIMPLEV_NULL: // 22
814 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700815 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 case CBOR_SIMPLEV_ONEBYTE: // 24
819 if(uNumber <= CBOR_SIMPLE_BREAK) {
820 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700821 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 goto Done;
823 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800824 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 default: // 0-19
828 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800829 /*
830 DecodeTypeAndNumber will make uNumber equal to
831 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
832 safe because the 2, 4 and 8 byte lengths of uNumber are in
833 the double/float cases above
834 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 pDecodedItem->val.uSimple = (uint8_t)uNumber;
836 break;
837 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839Done:
840 return nReturn;
841}
842
843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530845 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800847inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
848 int nMajorType,
849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800873 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530874 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800875 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530876 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700877 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530878 goto Done;
879 }
880 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800881 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882 } else {
883 // Normal case with no string allocator
884 pDecodedItem->val.string = Bytes;
885 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800886 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 // Cast because ternary operator causes promotion to integer
888 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
889 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 return nReturn;
893}
894
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897
898
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899
900
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901// Make sure the constants align as this is assumed by
902// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
904#error QCBOR_TYPE_ARRAY value not lined up with major type
905#endif
906#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
907#error QCBOR_TYPE_MAP value not lined up with major type
908#endif
909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800911 This gets a single data item and decodes it including preceding
912 optional tagging. This does not deal with arrays and maps and nesting
913 except to decode the data item introducing them. Arrays and maps are
914 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundbladeee851742020-01-08 08:37:05 -0800916 Errors detected here include: an array that is too long to decode,
917 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800919static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
920 QCBORItem *pDecodedItem,
921 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700923 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800924
Laurence Lundbladeee851742020-01-08 08:37:05 -0800925 /*
926 Get the major type and the number. Number could be length of more
927 bytes or the value depending on the major type nAdditionalInfo is
928 an encoding of the length of the uNumber and is needed to decode
929 floats and doubles
930 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700932 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800933 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700935 memset(pDecodedItem, 0, sizeof(QCBORItem));
936
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundbladeee851742020-01-08 08:37:05 -0800939 // Error out here if we got into trouble on the type and number. The
940 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700941 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladeee851742020-01-08 08:37:05 -0800945 // At this point the major type and the value are valid. We've got
946 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
949 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700951 nReturn = QCBOR_ERR_BAD_INT;
952 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800953 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700954 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
958 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
960 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
961 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
962 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530963 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700964 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700966 }
967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
970 case CBOR_MAJOR_TYPE_MAP: // Major type 5
971 // Record the number of items in the array or map
972 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
973 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
974 goto Done;
975 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700977 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800979 // type conversion OK because of check above
980 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800982 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
984 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700989 nReturn = QCBOR_ERR_BAD_INT;
990 } else {
991 pDecodedItem->val.uTagV = uNumber;
992 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
993 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800995
Laurence Lundbladeee851742020-01-08 08:37:05 -0800996 case CBOR_MAJOR_TYPE_SIMPLE:
997 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800998 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 default:
1002 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 nReturn = QCBOR_ERR_UNSUPPORTED;
1004 break;
1005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007Done:
1008 return nReturn;
1009}
1010
1011
1012
1013/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001014 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001015 individual chunk items together into one QCBORItem using the string
1016 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301018 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020static inline QCBORError
1021GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001023 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001024
1025 // Get pointer to string allocator. First use is to pass it to
1026 // GetNext_Item() when option is set to allocate for *every* string.
1027 // Second use here is to allocate space to coallese indefinite
1028 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001029 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1030 &(me->StringAllocator) :
1031 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001033 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001034 nReturn = GetNext_Item(&(me->InBuf),
1035 pDecodedItem,
1036 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 if(nReturn) {
1038 goto Done;
1039 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301042 // code in this function from here down can be eliminated. Run tests, except
1043 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001045 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001046 const uint8_t uStringType = pDecodedItem->uDataType;
1047 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048 goto Done; // no need to do any work here on non-string types
1049 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001051 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301052 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001053 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301056 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001057 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1059 goto Done;
1060 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001061
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001062 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001063 UsefulBufC FullString = NULLUsefulBufC;
1064
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001066 // Get item for next chunk
1067 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001068 // NULL string allocator passed here. Do not need to allocate
1069 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001070 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001072 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301075 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001076 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301079 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 break;
1081 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001082
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001083 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301084 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001085 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001086 if(StringChunkItem.uDataType != uStringType ||
1087 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001088 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 break;
1090 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001091
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301092 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 // The first time throurgh FullString.ptr is NULL and this is
1094 // equivalent to StringAllocator_Allocate()
1095 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1096 UNCONST_POINTER(FullString.ptr),
1097 FullString.len + StringChunkItem.val.string.len);
1098
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301100 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001101 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 break;
1103 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001104
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001105 // Copy new string chunk at the end of string so far.
1106 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001109 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1110 // Getting the item failed, clean up the allocated memory
1111 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001114Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 return nReturn;
1116}
1117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001119static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1120 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001121 return uTagVal;
1122 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001123 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001124 return me->auMappedTags[x];
1125 }
1126}
1127
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001128/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001129 Gets all optional tag data items preceding a data item that is not an
1130 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001132static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001135 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001136
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001137 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1138 CBOR_TAG_INVALID16,
1139 CBOR_TAG_INVALID16,
1140 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001141
Laurence Lundblade59289e52019-12-30 13:44:37 -08001142 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001143 for(;;) {
1144 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001145 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001149 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1150 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001152 break;
1153 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001155 // Is there room for the tag in the tags list?
1156 size_t uTagIndex;
1157 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001158 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001159 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160 }
1161 }
1162 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001163 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001165
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001166 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001167 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001171 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001172 break;
1173 }
1174 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001175 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001176 break;
1177 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001178 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1180 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001181 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1182 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001183 }
1184
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001185 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001187 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188
1189 } else {
1190 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 }
1192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194Done:
1195 return nReturn;
1196}
1197
1198
1199/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001200 This layer takes care of map entries. It combines the label and data
1201 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001202 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001203static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001204GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001205{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001206 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001208 if(nReturn)
1209 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001211 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001212 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001213 goto Done;
1214 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001216 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1217 // In a map and caller wants maps decoded, not treated as arrays
1218
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001219 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001220 // If in a map and the right decoding mode, get the label
1221
Laurence Lundbladeee851742020-01-08 08:37:05 -08001222 // Save label in pDecodedItem and get the next which will
1223 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001224 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001225 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001226 if(nReturn)
1227 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301229 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001230
1231 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1232 // strings are always good labels
1233 pDecodedItem->label.string = LabelItem.val.string;
1234 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1235 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001236 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001237 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1238 goto Done;
1239 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1240 pDecodedItem->label.int64 = LabelItem.val.int64;
1241 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1242 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1243 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1244 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1245 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1246 pDecodedItem->label.string = LabelItem.val.string;
1247 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1248 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1249 } else {
1250 // label is not an int or a string. It is an arrray
1251 // or a float or such and this implementation doesn't handle that.
1252 // Also, tags on labels are ignored.
1253 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1254 goto Done;
1255 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001256 }
1257 } else {
1258 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001259 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1260 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1261 goto Done;
1262 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001263 // Decoding a map as an array
1264 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001265 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1266 // Cast is needed because of integer promotion
1267 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001268 }
1269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001271Done:
1272 return nReturn;
1273}
1274
1275
Laurence Lundblade02625d42020-06-25 14:41:41 -07001276/*
1277 See if next item is a CBOR break. If it is, it is consumed,
1278 if not it is not consumed.
1279*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001280static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001281NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1282{
1283 *pbNextIsBreak = false;
1284 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001285 QCBORItem Peek;
1286 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1287 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1288 if(uReturn != QCBOR_SUCCESS) {
1289 return uReturn;
1290 }
1291 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001292 // It is not a break, rewind so it can be processed normally.
1293 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001294 } else {
1295 *pbNextIsBreak = true;
1296 }
1297 }
1298
1299 return QCBOR_SUCCESS;
1300}
1301
1302
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001304 An item was just consumed, now figure out if it was the
1305 end of an array or map that can be closed out. That
1306 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001308static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001309{
1310 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001311
Laurence Lundblade642282a2020-06-23 12:00:33 -07001312 /* This loops ascending nesting levels as long as there is ascending to do */
1313 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1314
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001315 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001316 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001317 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1318 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001319 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320 break;
1321 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001322 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001323
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001324 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001325 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001326 bool bIsBreak = false;
1327 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1328 if(uReturn != QCBOR_SUCCESS) {
1329 goto Done;
1330 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331
1332 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001333 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 break;
1335 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001337 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001338 /*
1339 Break occurred inside a bstr-wrapped CBOR or
1340 in the top level sequence. This is always an
1341 error because neither are an indefinte length
1342 map/array.
1343 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001344 uReturn = QCBOR_ERR_BAD_BREAK;
1345 goto Done;
1346 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001347
Laurence Lundblade02625d42020-06-25 14:41:41 -07001348 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001349 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001350
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001352
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001353 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001354 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001355 /* 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 -07001356 if(bMarkEnd) {
1357 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001358 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001359
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001360 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001361 break;
1362 }
1363
1364 /* Finally, actually ascend one level. */
1365 DecodeNesting_Ascend(&(pMe->nesting));
1366 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001367
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001368 uReturn = QCBOR_SUCCESS;
1369
1370Done:
1371 return uReturn;
1372}
1373
1374
1375/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001376 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001377 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1378 indefinte length maps and arrays by looking at the item count or
1379 finding CBOR breaks. It detects the ends of the top-level sequence
1380 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001381 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001382static QCBORError
1383QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001384{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001385 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001386 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001387
Laurence Lundblade642282a2020-06-23 12:00:33 -07001388 /*
1389 If out of bytes to consume, it is either the end of the top-level
1390 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001391
Laurence Lundblade642282a2020-06-23 12:00:33 -07001392 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1393 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1394 CBOR is exited, the length is set back to the top-level's length
1395 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001397 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001398 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001399 goto Done;
1400 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001401
Laurence Lundblade642282a2020-06-23 12:00:33 -07001402 /*
1403 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001404 array. The check for the end of an indefinite length array is
1405 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001406 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001407 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001408 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001409 goto Done;
1410 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001411
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001412 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001413 uReturn = GetNext_MapEntry(me, pDecodedItem);
1414 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001415 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001416 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301417
Laurence Lundblade642282a2020-06-23 12:00:33 -07001418 /*
1419 Breaks ending arrays/maps are always processed at the end of this
1420 function. They should never show up here.
1421 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301422 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001423 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301424 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301425 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001426
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427 /*
1428 Record the nesting level for this data item before processing any
1429 of decrementing and descending.
1430 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001431 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001432
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001434 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001435 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001436 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001437 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001438
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001439 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001440 of in the next chunk of code.
1441
1442 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001443 encloses them so a decrement needs to be done for them too, but
1444 that is done only when all the items in them have been
1445 processed, not when they are opened with the exception of an
1446 empty map or array.
1447 */
1448 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1449 pDecodedItem->uDataType,
1450 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001451 if(uReturn != QCBOR_SUCCESS) {
1452 goto Done;
1453 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001454 }
1455
Laurence Lundblade02625d42020-06-25 14:41:41 -07001456 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1457 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1458 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001459 /*
1460 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001461 - A non-aggregate like an integer or string
1462 - An empty definite length map or array
1463 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001465 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 definite length map/array and break detection for an indefinite
1467 length map/array. If the end of the map/array was reached, then
1468 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001469 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001470 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001471 if(uReturn) {
1472 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001473 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301474 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001475
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001476 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001478 Tell the caller what level is next. This tells them what
1479 maps/arrays were closed out and makes it possible for them to
1480 reconstruct the tree with just the information returned in
1481 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001482 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001483 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001484 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001485 pDecodedItem->uNextNestLevel = 0;
1486 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001487 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001488 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001489
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001490Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001491 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001492 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001493 memset(pDecodedItem, 0, sizeof(QCBORItem));
1494 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001495 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001496}
1497
1498
Laurence Lundblade59289e52019-12-30 13:44:37 -08001499/*
1500 Mostly just assign the right data type for the date string.
1501 */
1502inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1503{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001504 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1505 return QCBOR_ERR_BAD_OPT_TAG;
1506 }
1507
1508 const UsefulBufC Temp = pDecodedItem->val.string;
1509 pDecodedItem->val.dateString = Temp;
1510 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1511 return QCBOR_SUCCESS;
1512}
1513
1514
1515/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001516 The epoch formatted date. Turns lots of different forms of encoding
1517 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001518 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001519static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001520{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001521 QCBORError nReturn = QCBOR_SUCCESS;
1522
1523 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1524
1525 switch (pDecodedItem->uDataType) {
1526
1527 case QCBOR_TYPE_INT64:
1528 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1529 break;
1530
1531 case QCBOR_TYPE_UINT64:
1532 if(pDecodedItem->val.uint64 > INT64_MAX) {
1533 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1534 goto Done;
1535 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001536 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001537 break;
1538
1539 case QCBOR_TYPE_DOUBLE:
1540 {
1541 // This comparison needs to be done as a float before
1542 // conversion to an int64_t to be able to detect doubles
1543 // that are too large to fit into an int64_t. A double
1544 // has 52 bits of preceision. An int64_t has 63. Casting
1545 // INT64_MAX to a double actually causes a round up which
1546 // is bad and wrong for the comparison because it will
1547 // allow conversion of doubles that can't fit into a
1548 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1549 // the cutoff point as if that rounds up in conversion to
1550 // double it will still be less than INT64_MAX. 0x7ff is
1551 // picked because it has 11 bits set.
1552 //
1553 // INT64_MAX seconds is on the order of 10 billion years,
1554 // and the earth is less than 5 billion years old, so for
1555 // most uses this conversion error won't occur even though
1556 // doubles can go much larger.
1557 //
1558 // Without the 0x7ff there is a ~30 minute range of time
1559 // values 10 billion years in the past and in the future
1560 // where this this code would go wrong.
1561 const double d = pDecodedItem->val.dfnum;
1562 if(d > (double)(INT64_MAX - 0x7ff)) {
1563 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1564 goto Done;
1565 }
1566 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1567 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1568 }
1569 break;
1570
1571 default:
1572 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1573 goto Done;
1574 }
1575 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1576
1577Done:
1578 return nReturn;
1579}
1580
1581
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001582/*
1583 Mostly just assign the right data type for the bignum.
1584 */
1585inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1586{
1587 // Stack Use: UsefulBuf 1 -- 16
1588 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1589 return QCBOR_ERR_BAD_OPT_TAG;
1590 }
1591 const UsefulBufC Temp = pDecodedItem->val.string;
1592 pDecodedItem->val.bigNum = Temp;
1593 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1594 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1595 : QCBOR_TYPE_NEGBIGNUM);
1596 return QCBOR_SUCCESS;
1597}
1598
1599
Laurence Lundblade59289e52019-12-30 13:44:37 -08001600#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1601/*
1602 Decode decimal fractions and big floats.
1603
1604 When called pDecodedItem must be the array that is tagged as a big
1605 float or decimal fraction, the array that has the two members, the
1606 exponent and mantissa.
1607
1608 This will fetch and decode the exponent and mantissa and put the
1609 result back into pDecodedItem.
1610 */
1611inline static QCBORError
1612QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1613{
1614 QCBORError nReturn;
1615
1616 // --- Make sure it is an array; track nesting level of members ---
1617 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1618 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1619 goto Done;
1620 }
1621
1622 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001623 // definite length arrays, but not for indefnite. Instead remember
1624 // the nesting level the two integers must be at, which is one
1625 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001626 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1627
1628 // --- Is it a decimal fraction or a bigfloat? ---
1629 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1630 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1631
1632 // --- Get the exponent ---
1633 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001634 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001635 if(nReturn != QCBOR_SUCCESS) {
1636 goto Done;
1637 }
1638 if(exponentItem.uNestingLevel != nNestLevel) {
1639 // Array is empty or a map/array encountered when expecting an int
1640 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1641 goto Done;
1642 }
1643 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1644 // Data arriving as an unsigned int < INT64_MAX has been converted
1645 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1646 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1647 // will be too large for this to handle and thus an error that will
1648 // get handled in the next else.
1649 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1650 } else {
1651 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1652 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1653 goto Done;
1654 }
1655
1656 // --- Get the mantissa ---
1657 QCBORItem mantissaItem;
1658 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1659 if(nReturn != QCBOR_SUCCESS) {
1660 goto Done;
1661 }
1662 if(mantissaItem.uNestingLevel != nNestLevel) {
1663 // Mantissa missing or map/array encountered when expecting number
1664 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1665 goto Done;
1666 }
1667 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1668 // Data arriving as an unsigned int < INT64_MAX has been converted
1669 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1670 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1671 // will be too large for this to handle and thus an error that
1672 // will get handled in an else below.
1673 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1674 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1675 // Got a good big num mantissa
1676 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1677 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001678 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1679 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1680 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001681 } else {
1682 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1683 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1684 goto Done;
1685 }
1686
1687 // --- Check that array only has the two numbers ---
1688 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001689 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001690 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1691 goto Done;
1692 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001693 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694
1695Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001696 return nReturn;
1697}
1698#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1699
1700
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001701inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1702{
1703 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1704 return QCBOR_ERR_BAD_OPT_TAG;
1705 }
1706 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1707 return QCBOR_SUCCESS;
1708}
1709
1710
1711inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1712{
1713 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1714 return QCBOR_ERR_BAD_OPT_TAG;
1715 }
1716 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1717 return QCBOR_SUCCESS;
1718}
1719
1720
1721inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1722{
1723 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1724 return QCBOR_ERR_BAD_OPT_TAG;
1725 }
1726 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1727 return QCBOR_SUCCESS;
1728}
1729
1730
1731inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1732{
1733 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1734 return QCBOR_ERR_BAD_OPT_TAG;
1735 }
1736 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1737 return QCBOR_SUCCESS;
1738}
1739
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001740
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001741inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1742{
1743 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1744 return QCBOR_ERR_BAD_OPT_TAG;
1745 }
1746 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1747 return QCBOR_SUCCESS;
1748}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001749
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001750
1751inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1752{
1753 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1754 return QCBOR_ERR_BAD_OPT_TAG;
1755 }
1756 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1757 return QCBOR_SUCCESS;
1758}
1759
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001760
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001761inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1762{
1763 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1764 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001765 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001766 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1767 } else {
1768 return QCBOR_ERR_BAD_OPT_TAG;
1769 }
1770 return QCBOR_SUCCESS;
1771}
1772
1773
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001774inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1775{
1776 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1777 return QCBOR_ERR_BAD_OPT_TAG;
1778 }
1779 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1780 return QCBOR_SUCCESS;
1781}
1782
1783
Laurence Lundblade59289e52019-12-30 13:44:37 -08001784/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001785 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001786 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001787QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001788QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789{
1790 QCBORError nReturn;
1791
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001792 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001793 if(nReturn != QCBOR_SUCCESS) {
1794 goto Done;
1795 }
1796
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001797 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1798 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001799
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001800 // Many of the functions here only just map a CBOR tag to
1801 // a QCBOR_TYPE for a string and could probably be
1802 // implemented with less object code. This implementation
1803 // of string types takes about 120 bytes of object code
1804 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001805 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001806 nReturn = DecodeDateString(pDecodedItem);
1807 break;
1808
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001809 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001810 nReturn = DecodeDateEpoch(pDecodedItem);
1811 break;
1812
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001813 case CBOR_TAG_POS_BIGNUM:
1814 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001815 nReturn = DecodeBigNum(pDecodedItem);
1816 break;
1817
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001818 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1819 case CBOR_TAG_DECIMAL_FRACTION:
1820 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001821 // For aggregate tagged types, what goes into pTags is only collected
1822 // from the surrounding data item, not the contents, so pTags is not
1823 // passed on here.
1824
1825 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1826 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001827 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001828
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001829 case CBOR_TAG_CBOR:
1830 nReturn = DecodeWrappedCBOR(pDecodedItem);
1831 break;
1832
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001833 case CBOR_TAG_CBOR_SEQUENCE:
1834 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1835 break;
1836
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001837 case CBOR_TAG_URI:
1838 nReturn = DecodeURI(pDecodedItem);
1839 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001840
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001841 case CBOR_TAG_B64URL:
1842 nReturn = DecodeB64URL(pDecodedItem);
1843 break;
1844
1845 case CBOR_TAG_B64:
1846 nReturn = DecodeB64(pDecodedItem);
1847 break;
1848
1849 case CBOR_TAG_MIME:
1850 case CBOR_TAG_BINARY_MIME:
1851 nReturn = DecodeMIME(pDecodedItem);
1852 break;
1853
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001854 case CBOR_TAG_REGEX:
1855 nReturn = DecodeRegex(pDecodedItem);
1856 break;
1857
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001858 case CBOR_TAG_BIN_UUID:
1859 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001860 break;
1861
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001862 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001863 // The end of the tag list or no tags
1864 // Successful exit from the loop.
1865 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001866
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001867 default:
1868 // A tag that is not understood
1869 // A successful exit from the loop
1870 goto Done;
1871
1872 }
1873 if(nReturn != QCBOR_SUCCESS) {
1874 goto Done;
1875 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001876 }
1877
1878Done:
1879 if(nReturn != QCBOR_SUCCESS) {
1880 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1881 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1882 }
1883 return nReturn;
1884}
1885
1886
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001887QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1888{
1889 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1890
1891 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1892
1893 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07001894 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001895
1896 return uErr;
1897}
1898
1899
Laurence Lundblade59289e52019-12-30 13:44:37 -08001900/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001901 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001902 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001903QCBORError
1904QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1905 QCBORItem *pDecodedItem,
1906 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001907{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001908 QCBORError nReturn;
1909
1910 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1911 if(nReturn != QCBOR_SUCCESS) {
1912 return nReturn;
1913 }
1914
1915 if(pTags != NULL) {
1916 pTags->uNumUsed = 0;
1917 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001918 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001919 break;
1920 }
1921 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1922 return QCBOR_ERR_TOO_MANY_TAGS;
1923 }
1924 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1925 pTags->uNumUsed++;
1926 }
1927 }
1928
1929 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001930}
1931
1932
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001933/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301934 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301935 next one down. If a layer has no work to do for a particular item
1936 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001937
Laurence Lundblade59289e52019-12-30 13:44:37 -08001938 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1939 tagged data items, turning them into the local C representation.
1940 For the most simple it is just associating a QCBOR_TYPE with the data. For
1941 the complex ones that an aggregate of data items, there is some further
1942 decoding and a little bit of recursion.
1943
1944 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301945 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301946 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001947 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001948
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301949 - GetNext_MapEntry -- This handles the combining of two
1950 items, the label and the data, that make up a map entry.
1951 It only does work on maps. It combines the label and data
1952 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001953
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1955 tags into bit flags associated with the data item. No actual decoding
1956 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001957
Laurence Lundblade59289e52019-12-30 13:44:37 -08001958 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301959 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301960 string allocater to create contiguous space for the item. It
1961 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001962
Laurence Lundblade59289e52019-12-30 13:44:37 -08001963 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1964 atomic data item has a "major type", an integer "argument" and optionally
1965 some content. For text and byte strings, the content is the bytes
1966 that make up the string. These are the smallest data items that are
1967 considered to be well-formed. The content may also be other data items in
1968 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001969
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001970 Roughly this takes 300 bytes of stack for vars. Need to
1971 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001972
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301973 */
1974
1975
1976/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001978 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07001979bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001980 const QCBORItem *pItem,
1981 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001982{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001983 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001984 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001985 break;
1986 }
1987 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07001988 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001989 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001990 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001991
Laurence Lundbladef71e1622020-08-06 18:52:13 -07001992 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001993}
1994
1995
1996/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001997 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001998 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001999QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002000{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002001 QCBORError uReturn = me->uLastError;
2002
2003 if(uReturn != QCBOR_SUCCESS) {
2004 goto Done;
2005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002006
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002007 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002008 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002009 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002010 goto Done;
2011 }
2012
2013 // Error out if not all the bytes are consumed
2014 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002015 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002016 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002017
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002018Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302019 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002020 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002021 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002022
Laurence Lundblade085d7952020-07-24 10:26:30 -07002023 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002024}
2025
2026
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002027/*
2028Public function, see header qcbor/qcbor_decode.h file
2029*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002030uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2031 const QCBORItem *pItem,
2032 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002033{
2034 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2035 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002036 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002037 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002038 }
2039}
2040
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002041
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002042/*
2043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002044Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002045
Laurence Lundbladeee851742020-01-08 08:37:05 -08002046 - Hit end of input before it was expected while decoding type and
2047 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002048
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002049 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002050
Laurence Lundbladeee851742020-01-08 08:37:05 -08002051 - Hit end of input while decoding a text or byte string
2052 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundbladeee851742020-01-08 08:37:05 -08002054 - Encountered conflicting tags -- e.g., an item is tagged both a date
2055 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002056
Laurence Lundbladeee851742020-01-08 08:37:05 -08002057 - Encontered an array or mapp that has too many items
2058 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002059
Laurence Lundbladeee851742020-01-08 08:37:05 -08002060 - Encountered array/map nesting that is too deep
2061 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002062
Laurence Lundbladeee851742020-01-08 08:37:05 -08002063 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2064 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002065
Laurence Lundbladeee851742020-01-08 08:37:05 -08002066 - The type of a map label is not a string or int
2067 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002068
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002069 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002070
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002071 */
2072
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002073
2074
Laurence Lundbladef6531662018-12-04 10:42:22 +09002075
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002076/* ===========================================================================
2077 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002078
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002079 This implements a simple sting allocator for indefinite length
2080 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2081 implements the function type QCBORStringAllocate and allows easy
2082 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002083
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002084 This particular allocator is built-in for convenience. The caller
2085 can implement their own. All of this following code will get
2086 dead-stripped if QCBORDecode_SetMemPool() is not called.
2087
2088 This is a very primitive memory allocator. It does not track
2089 individual allocations, only a high-water mark. A free or
2090 reallocation must be of the last chunk allocated.
2091
2092 The size of the pool and offset to free memory are packed into the
2093 first 8 bytes of the memory pool so we don't have to keep them in
2094 the decode context. Since the address of the pool may not be
2095 aligned, they have to be packed and unpacked as if they were
2096 serialized data of the wire or such.
2097
2098 The sizes packed in are uint32_t to be the same on all CPU types
2099 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002100 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002101
2102
Laurence Lundbladeee851742020-01-08 08:37:05 -08002103static inline int
2104MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002105{
2106 // Use of UsefulInputBuf is overkill, but it is convenient.
2107 UsefulInputBuf UIB;
2108
Laurence Lundbladeee851742020-01-08 08:37:05 -08002109 // Just assume the size here. It was checked during SetUp so
2110 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002111 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2112 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2113 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2114 return UsefulInputBuf_GetError(&UIB);
2115}
2116
2117
Laurence Lundbladeee851742020-01-08 08:37:05 -08002118static inline int
2119MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002120{
2121 // Use of UsefulOutBuf is overkill, but convenient. The
2122 // length check performed here is useful.
2123 UsefulOutBuf UOB;
2124
2125 UsefulOutBuf_Init(&UOB, Pool);
2126 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2127 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2128 return UsefulOutBuf_GetError(&UOB);
2129}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002130
2131
2132/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002133 Internal function for an allocation, reallocation free and destuct.
2134
2135 Having only one function rather than one each per mode saves space in
2136 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002137
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002138 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2139 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002140static UsefulBuf
2141MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002142{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002143 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002144
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002145 uint32_t uPoolSize;
2146 uint32_t uFreeOffset;
2147
2148 if(uNewSize > UINT32_MAX) {
2149 // This allocator is only good up to 4GB. This check should
2150 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2151 goto Done;
2152 }
2153 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2154
2155 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2156 goto Done;
2157 }
2158
2159 if(uNewSize) {
2160 if(pMem) {
2161 // REALLOCATION MODE
2162 // Calculate pointer to the end of the memory pool. It is
2163 // assumed that pPool + uPoolSize won't wrap around by
2164 // assuming the caller won't pass a pool buffer in that is
2165 // not in legitimate memory space.
2166 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2167
2168 // Check that the pointer for reallocation is in the range of the
2169 // pool. This also makes sure that pointer math further down
2170 // doesn't wrap under or over.
2171 if(pMem >= pPool && pMem < pPoolEnd) {
2172 // Offset to start of chunk for reallocation. This won't
2173 // wrap under because of check that pMem >= pPool. Cast
2174 // is safe because the pool is always less than UINT32_MAX
2175 // because of check in QCBORDecode_SetMemPool().
2176 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2177
2178 // Check to see if the allocation will fit. uPoolSize -
2179 // uMemOffset will not wrap under because of check that
2180 // pMem is in the range of the uPoolSize by check above.
2181 if(uNewSize <= uPoolSize - uMemOffset) {
2182 ReturnValue.ptr = pMem;
2183 ReturnValue.len = uNewSize;
2184
2185 // Addition won't wrap around over because uNewSize was
2186 // checked to be sure it is less than the pool size.
2187 uFreeOffset = uMemOffset + uNewSize32;
2188 }
2189 }
2190 } else {
2191 // ALLOCATION MODE
2192 // uPoolSize - uFreeOffset will not underflow because this
2193 // pool implementation makes sure uFreeOffset is always
2194 // smaller than uPoolSize through this check here and
2195 // reallocation case.
2196 if(uNewSize <= uPoolSize - uFreeOffset) {
2197 ReturnValue.len = uNewSize;
2198 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002199 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002200 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002201 }
2202 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002203 if(pMem) {
2204 // FREE MODE
2205 // Cast is safe because of limit on pool size in
2206 // QCBORDecode_SetMemPool()
2207 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2208 } else {
2209 // DESTRUCT MODE
2210 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002211 }
2212 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002213
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002214 UsefulBuf Pool = {pPool, uPoolSize};
2215 MemPool_Pack(Pool, uFreeOffset);
2216
2217Done:
2218 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002219}
2220
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002221
Laurence Lundbladef6531662018-12-04 10:42:22 +09002222/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002223 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002224 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002225QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2226 UsefulBuf Pool,
2227 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002228{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002229 // The pool size and free mem offset are packed into the beginning
2230 // of the pool memory. This compile time check make sure the
2231 // constant in the header is correct. This check should optimize
2232 // down to nothing.
2233 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002234 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002235 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002236
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002237 // The pool size and free offset packed in to the beginning of pool
2238 // memory are only 32-bits. This check will optimize out on 32-bit
2239 // machines.
2240 if(Pool.len > UINT32_MAX) {
2241 return QCBOR_ERR_BUFFER_TOO_LARGE;
2242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002243
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002244 // This checks that the pool buffer given is big enough.
2245 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2246 return QCBOR_ERR_BUFFER_TOO_SMALL;
2247 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002249 pMe->StringAllocator.pfAllocator = MemPool_Function;
2250 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2251 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002252
Laurence Lundblade30816f22018-11-10 13:40:22 +07002253 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002254}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002255
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002256
2257
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002258
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002259
2260
2261/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002262 Consume an entire map or array (and do next to
2263 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002264 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002265static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002266ConsumeItem(QCBORDecodeContext *pMe,
2267 const QCBORItem *pItemToConsume,
2268 uint_fast8_t *puNextNestLevel)
2269{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002270 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002271 QCBORItem Item;
2272
Laurence Lundblade02625d42020-06-25 14:41:41 -07002273 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002274
Laurence Lundblade02625d42020-06-25 14:41:41 -07002275 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002277
Laurence Lundblade1341c592020-04-11 14:19:05 -07002278 /* This works for definite and indefinite length
2279 * maps and arrays by using the nesting level
2280 */
2281 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002282 uReturn = QCBORDecode_GetNext(pMe, &Item);
2283 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002284 goto Done;
2285 }
2286 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002287
Laurence Lundblade1341c592020-04-11 14:19:05 -07002288 if(puNextNestLevel != NULL) {
2289 *puNextNestLevel = Item.uNextNestLevel;
2290 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002291 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002292
Laurence Lundblade1341c592020-04-11 14:19:05 -07002293 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002294 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002295 if(puNextNestLevel != NULL) {
2296 /* Just pass the nesting level through */
2297 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2298 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002299 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002300 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301
2302Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002303 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002304}
2305
2306
Laurence Lundblade1341c592020-04-11 14:19:05 -07002307/* Return true if the labels in Item1 and Item2 are the same.
2308 Works only for integer and string labels. Returns false
2309 for any other type. */
2310static inline bool
2311MatchLabel(QCBORItem Item1, QCBORItem Item2)
2312{
2313 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2314 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2315 return true;
2316 }
2317 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002318 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002319 return true;
2320 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002321 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002322 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2323 return true;
2324 }
2325 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2326 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2327 return true;
2328 }
2329 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002330
Laurence Lundblade1341c592020-04-11 14:19:05 -07002331 /* Other label types are never matched */
2332 return false;
2333}
2334
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002335
2336/*
2337 Returns true if Item1 and Item2 are the same type
2338 or if either are of QCBOR_TYPE_ANY.
2339 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002340static inline bool
2341MatchType(QCBORItem Item1, QCBORItem Item2)
2342{
2343 if(Item1.uDataType == Item2.uDataType) {
2344 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002345 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002346 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002347 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002348 return true;
2349 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002350 return false;
2351}
2352
2353
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002354/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002355 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002356
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002357 @param[in] pMe The decode context to search.
2358 @param[in,out] pItemArray The items to search for and the items found.
2359 @param[out] puOffset Byte offset of last item matched.
2360 @param[in] pCBContext Context for the not-found item call back.
2361 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002362
2363 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2364
2365 @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.
2366
2367 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2368
2369 @retval Also errors returned by QCBORDecode_GetNext().
2370
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002371 On input pItemArray contains a list of labels and data types
2372 of items to be found.
2373
2374 On output the fully retrieved items are filled in with
2375 values and such. The label was matched, so it never changes.
2376
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002377 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002378 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002379static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002380MapSearch(QCBORDecodeContext *pMe,
2381 QCBORItem *pItemArray,
2382 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002383 void *pCBContext,
2384 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002385{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002386 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002387 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002388
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002389 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002390 uReturn = pMe->uLastError;
2391 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002392 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002393
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002394 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002395 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2396 /* QCBOR_TYPE_NONE as first item indicates just looking
2397 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002398 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2399 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002400 }
2401
Laurence Lundblade085d7952020-07-24 10:26:30 -07002402 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2403 // It is an empty bounded array or map
2404 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2405 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002406 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002407 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002408 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002409 // Nothing is ever found in an empty array or map. All items
2410 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002411 uReturn = QCBOR_SUCCESS;
2412 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002413 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002414 }
2415
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002416 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002417 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2418
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002419 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002420 UsefulInputBuf_Seek(&(pMe->InBuf),
2421 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002422
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002423 /*
2424 Loop over all the items in the map. They could be
2425 deeply nested and this should handle both definite
2426 and indefinite length maps and arrays, so this
2427 adds some complexity.
2428 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002429 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002430 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002431 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002432 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002433 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002434
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002435 /* Get the item */
2436 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002437 uReturn = QCBORDecode_GetNext(pMe, &Item);
2438 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002439 /* Got non-well-formed CBOR */
2440 goto Done;
2441 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002442
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002443 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002444 bool bMatched = false;
2445 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2446 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002447 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002448 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2449 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002450 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002451 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002452 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002453 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002454 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002455 goto Done;
2456 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002457
Laurence Lundblade1341c592020-04-11 14:19:05 -07002458 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002459 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002460 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002461 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002463 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002464 bMatched = true;
2465 }
2466 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002467
2468
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002469 if(!bMatched && pfCallback != NULL) {
2470 /*
2471 Call the callback on unmatched labels.
2472 (It is tempting to do duplicate detection here, but that would
2473 require dynamic memory allocation because the number of labels
2474 that might be encountered is unbounded.)
2475 */
2476 uReturn = (*pfCallback)(pCBContext, &Item);
2477 if(uReturn != QCBOR_SUCCESS) {
2478 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479 }
2480 }
2481
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002482 /*
2483 Consume the item whether matched or not. This
2484 does the work of traversing maps and array and
2485 everything in them. In this loop only the
2486 items at the current nesting level are examined
2487 to match the labels.
2488 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002489 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2490 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 goto Done;
2492 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002493
2494 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002495
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002496 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002497
2498 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002499 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2500 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002501
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002502 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002503 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2504
2505 Done2:
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002506 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2507 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002508 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002509 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002510 }
2511 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002512
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002513 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002514}
2515
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002517/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002518 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002519*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002520void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2521 int64_t nLabel,
2522 uint8_t uQcborType,
2523 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002525 if(pMe->uLastError != QCBOR_SUCCESS) {
2526 return;
2527 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002528
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002529 QCBORItem OneItemSeach[2];
2530 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2531 OneItemSeach[0].label.int64 = nLabel;
2532 OneItemSeach[0].uDataType = uQcborType;
2533 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002534
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002535 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2536 if(uReturn != QCBOR_SUCCESS) {
2537 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002538 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002539 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002540 uReturn = QCBOR_ERR_NOT_FOUND;
2541 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542 }
2543
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002544 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002545
2546 Done:
2547 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002548}
2549
2550
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002551/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002552 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002553*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002554void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2555 const char *szLabel,
2556 uint8_t uQcborType,
2557 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002558{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002559 if(pMe->uLastError != QCBOR_SUCCESS) {
2560 return;
2561 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002562
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002563 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002564 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2565 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2566 OneItemSeach[0].uDataType = uQcborType;
2567 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002568
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002569 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2570 if(uReturn != QCBOR_SUCCESS) {
2571 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002572 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002573 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002574 uReturn = QCBOR_ERR_NOT_FOUND;
2575 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002576 }
2577
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002578 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002579
2580Done:
2581 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002582}
2583
2584
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002585
2586static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2587{
2588 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2589 if(uDataType == puTypeList[i]) {
2590 return QCBOR_SUCCESS;
2591 }
2592 }
2593 return QCBOR_ERR_UNEXPECTED_TYPE;
2594}
2595
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002596
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002597/**
2598 @param[in] TagSpec Specification for matching tags.
2599 @param[in] uDataType A QCBOR data type
2600
2601 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2602 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2603
2604 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2605 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002606static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002607{
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002608 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002609 // Must match the tag and only the tag
2610 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002611 }
2612
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002613 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2614 if(uReturn == QCBOR_SUCCESS) {
2615 return QCBOR_SUCCESS;
2616 }
2617
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002618 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002619 /* Must match the content type and only the content type.
2620 There was no match just above so it is a fail. */
2621 return QCBOR_ERR_UNEXPECTED_TYPE;
2622 }
2623
2624 /* If here it can match either the tag or the content
2625 and it hasn't matched the content, so the end
2626 result is whether it matches the tag. This is
2627 also the case that the CBOR standard discourages. */
2628
2629 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002630}
2631
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002632
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002633// Semi-private
2634// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002635void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2636 int64_t nLabel,
2637 TagSpecification TagSpec,
2638 QCBORItem *pItem)
2639{
2640 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2641 if(pMe->uLastError != QCBOR_SUCCESS) {
2642 return;
2643 }
2644
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002645 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002646}
2647
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002648// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002649void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2650 const char *szLabel,
2651 TagSpecification TagSpec,
2652 QCBORItem *pItem)
2653{
2654 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2655 if(pMe->uLastError != QCBOR_SUCCESS) {
2656 return;
2657 }
2658
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002659 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002660}
2661
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002662// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002663void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2664 int64_t nLabel,
2665 TagSpecification TagSpec,
2666 UsefulBufC *pString)
2667{
2668 QCBORItem Item;
2669 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2670 if(pMe->uLastError == QCBOR_SUCCESS) {
2671 *pString = Item.val.string;
2672 }
2673}
2674
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002675// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002676void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2677 const char * szLabel,
2678 TagSpecification TagSpec,
2679 UsefulBufC *pString)
2680{
2681 QCBORItem Item;
2682 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2683 if(pMe->uLastError == QCBOR_SUCCESS) {
2684 *pString = Item.val.string;
2685 }
2686}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002687
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002688/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002689 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002690*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002691QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2692{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002693 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002694}
2695
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002696/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002697 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002698*/
2699QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2700 QCBORItem *pItemList,
2701 void *pCallbackCtx,
2702 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002703{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002704 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002705}
2706
2707
Laurence Lundblade34691b92020-05-18 22:25:25 -07002708static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002709{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002710 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002711 if(pMe->uLastError != QCBOR_SUCCESS) {
2712 // Already in error state; do nothing.
2713 return;
2714 }
2715
2716 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002717 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002718 if(pMe->uLastError != QCBOR_SUCCESS) {
2719 return;
2720 }
2721
Laurence Lundblade085d7952020-07-24 10:26:30 -07002722 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2723 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2724 return;
2725 }
2726
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002727 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002728 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002729
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002730 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002731 be at the right place.
2732
2733 The UsefulInBuf offset could be anywhere, so no assumption is
2734 made about it.
2735
2736 No assumption is made about the pre-order nesting level either.
2737
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002738 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002739 the map level that is being entered.
2740 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002741 /* Seek to the data item that is the map or array */
2742 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002743
2744 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002745
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002746 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747}
2748
2749
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002750/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002751 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002752*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002753void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002754{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002755 QCBORItem OneItemSeach[2];
2756 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2757 OneItemSeach[0].label.int64 = nLabel;
2758 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2759 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002760
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002761 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002762 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002763}
2764
2765
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002766/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002767 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002768*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002769void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002770{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002771 QCBORItem OneItemSeach[2];
2772 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2773 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2774 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2775 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002776
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002777 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778}
2779
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002780/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002781 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002782*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002783void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002784{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002785 QCBORItem OneItemSeach[2];
2786 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2787 OneItemSeach[0].label.int64 = nLabel;
2788 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2789 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002790
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002791 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002792}
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_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2798{
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_ARRAY;
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 Lundblade1341c592020-04-11 14:19:05 -07002806}
2807
2808
Laurence Lundblade02625d42020-06-25 14:41:41 -07002809// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002810void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002811{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002812 QCBORError uErr;
2813
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002814 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002815 if(pMe->uLastError != QCBOR_SUCCESS) {
2816 // Already in error state; do nothing.
2817 return;
2818 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002819
2820 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002821 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002822 uErr = QCBORDecode_GetNext(pMe, &Item);
2823 if(uErr != QCBOR_SUCCESS) {
2824 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002825 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002826 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002827 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2828 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829 }
2830
Laurence Lundbladef0499502020-08-01 11:55:57 -07002831 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002832 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002833 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2834 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002835 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002836 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2837 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002838 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2839 DecodeNesting_Descend(&(pMe->nesting), uType);
2840 }
2841
Laurence Lundblade02625d42020-06-25 14:41:41 -07002842 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002843
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002844 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2845 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002846
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002847Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002848 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002849}
2850
Laurence Lundblade02625d42020-06-25 14:41:41 -07002851
2852/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002853 This is the common work for exiting a level that is a bounded map, array or bstr
2854 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002855
2856 One chunk of work is to set up the pre-order traversal so it is at
2857 the item just after the bounded map, array or bstr that is being
2858 exited. This is somewhat complex.
2859
2860 The other work is to level-up the bounded mode to next higest bounded
2861 mode or the top level if there isn't one.
2862 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002863static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002864ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002865{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002866 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002867
Laurence Lundblade02625d42020-06-25 14:41:41 -07002868 /*
2869 First the pre-order-traversal byte offset is positioned to the
2870 item just after the bounded mode item that was just consumed.
2871 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002872 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2873
Laurence Lundblade02625d42020-06-25 14:41:41 -07002874 /*
2875 Next, set the current nesting level to one above the bounded level
2876 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002877
Laurence Lundblade02625d42020-06-25 14:41:41 -07002878 DecodeNesting_CheckBoundedType() is always called before this and
2879 makes sure pCurrentBounded is valid.
2880 */
2881 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2882
2883 /*
2884 This does the complex work of leveling up the pre-order traversal
2885 when the end of a map or array or another bounded level is
2886 reached. It may do nothing, or ascend all the way to the top
2887 level.
2888 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002889 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002890 if(uErr != QCBOR_SUCCESS) {
2891 goto Done;
2892 }
2893
Laurence Lundblade02625d42020-06-25 14:41:41 -07002894 /*
2895 This makes the next highest bounded level the current bounded
2896 level. If there is no next highest level, then no bounded mode is
2897 in effect.
2898 */
2899 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002900
Laurence Lundblade02625d42020-06-25 14:41:41 -07002901 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002902
2903Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002904 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002905 return uErr;
2906}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002907
Laurence Lundblade02625d42020-06-25 14:41:41 -07002908
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002909// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002910void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002911{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002912 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002913 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002914 return;
2915 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002916
Laurence Lundblade02625d42020-06-25 14:41:41 -07002917 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002918
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002919 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002920 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2921 goto Done;
2922 }
2923
Laurence Lundblade02625d42020-06-25 14:41:41 -07002924 /*
2925 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002926 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002927 from previous map search, then do a dummy search.
2928 */
2929 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002930 QCBORItem Dummy;
2931 Dummy.uLabelType = QCBOR_TYPE_NONE;
2932 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2933 if(uErr != QCBOR_SUCCESS) {
2934 goto Done;
2935 }
2936 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002937
Laurence Lundblade02625d42020-06-25 14:41:41 -07002938 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002939
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002940Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002941 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002942}
2943
2944
Laurence Lundblade1341c592020-04-11 14:19:05 -07002945
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002946static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002947 const QCBORItem *pItem,
2948 uint8_t uTagRequirement,
2949 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002950{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002951 if(pBstr) {
2952 *pBstr = NULLUsefulBufC;
2953 }
2954
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002955 if(pMe->uLastError != QCBOR_SUCCESS) {
2956 // Already in error state; do nothing.
2957 return pMe->uLastError;
2958 }
2959
2960 QCBORError uError = QCBOR_SUCCESS;
2961
2962 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2963 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2964 goto Done;;
2965 }
2966
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002967 const TagSpecification TagSpec =
2968 {
2969 uTagRequirement,
2970 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2971 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2972 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002973
2974 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2975 if(uError != QCBOR_SUCCESS) {
2976 goto Done;
2977 }
2978
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002979 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002980 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002981 so the increment in NestLevelAscender called by ExitBoundedLevel()
2982 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002983 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002984 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002985
2986 if(pBstr) {
2987 *pBstr = pItem->val.string;
2988 }
2989
2990 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002991
2992 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07002993 // Most of these calls are simple inline accessors so this doesn't
2994 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002995 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07002996 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
2997 // TODO: test this error condition
2998 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
2999 goto Done;
3000 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003001 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003002 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003003
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003004 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003005 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003006 (uint32_t)uPreviousLength,
3007 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003008Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003009 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003010
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003011 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003012}
3013
3014
Laurence Lundblade02625d42020-06-25 14:41:41 -07003015/*
3016 Public function, see header qcbor/qcbor_decode.h file
3017 */
3018void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003019 uint8_t uTagRequirement,
3020 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003021{
3022 if(pMe->uLastError != QCBOR_SUCCESS) {
3023 // Already in error state; do nothing.
3024 return;
3025 }
3026
3027 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003028 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003029 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3030 if(pMe->uLastError != QCBOR_SUCCESS) {
3031 return;
3032 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003033
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003034 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003035 &Item,
3036 uTagRequirement,
3037 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003038}
3039
3040
Laurence Lundblade02625d42020-06-25 14:41:41 -07003041/*
3042 Public function, see header qcbor/qcbor_decode.h file
3043 */
3044void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003045 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003046 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003047 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003048{
3049 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003050 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003051
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003052 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003053}
3054
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003055
Laurence Lundblade02625d42020-06-25 14:41:41 -07003056/*
3057 Public function, see header qcbor/qcbor_decode.h file
3058 */
3059void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003060 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003061 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003062 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003063{
3064 QCBORItem Item;
3065 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3066
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003067 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003068}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003069
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003070
Laurence Lundblade02625d42020-06-25 14:41:41 -07003071/*
3072 Public function, see header qcbor/qcbor_decode.h file
3073 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003074void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003075{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003076 if(pMe->uLastError != QCBOR_SUCCESS) {
3077 // Already in error state; do nothing.
3078 return;
3079 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003080
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003081 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003082 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3083 return;
3084 }
3085
3086 /*
3087 Reset the length of the UsefulInputBuf to what it was before
3088 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003089 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003090 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3091 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003092
3093
Laurence Lundblade02625d42020-06-25 14:41:41 -07003094 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003095 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003096}
3097
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003098
Laurence Lundbladee6430642020-03-14 21:15:44 -07003099
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003100
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003101
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003102
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003103
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003104
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003105static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3106{
3107 switch(pItem->uDataType) {
3108 case QCBOR_TYPE_TRUE:
3109 *pBool = true;
3110 return QCBOR_SUCCESS;
3111 break;
3112
3113 case QCBOR_TYPE_FALSE:
3114 *pBool = false;
3115 return QCBOR_SUCCESS;
3116 break;
3117
3118 default:
3119 return QCBOR_ERR_UNEXPECTED_TYPE;
3120 break;
3121 }
3122}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003123
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003124
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003125/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003126 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003127*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003128void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003129{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003130 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003131 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003132 return;
3133 }
3134
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135 QCBORError nError;
3136 QCBORItem Item;
3137
3138 nError = QCBORDecode_GetNext(pMe, &Item);
3139 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003140 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003141 return;
3142 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144}
3145
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003146
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003147/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003148 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003149*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003150void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003151{
3152 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003153 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003154
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003155 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003156}
3157
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003158
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003159/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003160 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003161*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003162void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3163{
3164 QCBORItem Item;
3165 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3166
3167 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3168}
3169
3170
3171
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003172void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3173 TagSpecification TagSpec,
3174 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003175{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003176 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003177 // Already in error state, do nothing
3178 return;
3179 }
3180
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003181 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003182 QCBORItem Item;
3183
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003184 uError = QCBORDecode_GetNext(pMe, &Item);
3185 if(uError != QCBOR_SUCCESS) {
3186 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003187 return;
3188 }
3189
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003190 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3191
3192 if(pMe->uLastError == QCBOR_SUCCESS) {
3193 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003194 }
3195}
3196
Laurence Lundbladec4537442020-04-14 18:53:22 -07003197
3198
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003199
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003200static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003201 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003202 UsefulBufC *pValue,
3203 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003204{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003205 const TagSpecification TagSpec =
3206 {
3207 uTagRequirement,
3208 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3209 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3210 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003211
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003212 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3213 if(uErr != QCBOR_SUCCESS) {
3214 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003215 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003216
3217 *pValue = pItem->val.string;
3218
3219 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3220 *pbIsNegative = false;
3221 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3222 *pbIsNegative = true;
3223 }
3224
3225 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003226}
3227
3228
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003229/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003230 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003231 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003232void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3233 uint8_t uTagRequirement,
3234 UsefulBufC *pValue,
3235 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003236{
3237 if(pMe->uLastError != QCBOR_SUCCESS) {
3238 // Already in error state, do nothing
3239 return;
3240 }
3241
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003242 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003243 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3244 if(uError != QCBOR_SUCCESS) {
3245 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003246 return;
3247 }
3248
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003249 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003250}
3251
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003252
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003253/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003254 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003255*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003256void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3257 int64_t nLabel,
3258 uint8_t uTagRequirement,
3259 UsefulBufC *pValue,
3260 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003262 QCBORItem Item;
3263 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003264 if(pMe->uLastError != QCBOR_SUCCESS) {
3265 return;
3266 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003267
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003268 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003269}
3270
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003271
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003272/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003273 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003274*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003275void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3276 const char *szLabel,
3277 uint8_t uTagRequirement,
3278 UsefulBufC *pValue,
3279 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003280{
3281 QCBORItem Item;
3282 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003283 if(pMe->uLastError != QCBOR_SUCCESS) {
3284 return;
3285 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003286
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003287 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003288}
3289
3290
3291
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003292
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003293// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003294QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3295 const QCBORItem *pItem,
3296 UsefulBufC *pMessage,
3297 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003298{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003299 const TagSpecification TagSpecText =
3300 {
3301 uTagRequirement,
3302 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3303 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3304 };
3305 const TagSpecification TagSpecBinary =
3306 {
3307 uTagRequirement,
3308 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3309 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3310 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003311
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003312 QCBORError uReturn;
3313
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003314 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003315 *pMessage = pItem->val.string;
3316 if(pbIsNot7Bit != NULL) {
3317 *pbIsNot7Bit = false;
3318 }
3319 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003320 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003321 *pMessage = pItem->val.string;
3322 if(pbIsNot7Bit != NULL) {
3323 *pbIsNot7Bit = true;
3324 }
3325 uReturn = QCBOR_SUCCESS;
3326
3327 } else {
3328 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3329 }
3330
3331 return uReturn;
3332}
3333
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003334// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3335
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003336
3337
3338
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003339#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003340
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003341typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003342
3343
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003344// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003345static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003346{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003347 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003348
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003349 if(uResult != 0) {
3350 /* This loop will run a maximum of 19 times because
3351 * UINT64_MAX < 10 ^^ 19. More than that will cause
3352 * exit with the overflow error
3353 */
3354 for(; nExponent > 0; nExponent--) {
3355 if(uResult > UINT64_MAX / 10) {
3356 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3357 }
3358 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003359 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003360
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003361 for(; nExponent < 0; nExponent++) {
3362 uResult = uResult / 10;
3363 if(uResult == 0) {
3364 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3365 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003366 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003367 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003368 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003369
3370 *puResult = uResult;
3371
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003373}
3374
3375
Laurence Lundbladee6430642020-03-14 21:15:44 -07003376/* Convert a decimal fraction to an int64_t without using
3377 floating point or math libraries. Most decimal fractions
3378 will not fit in an int64_t and this will error out with
3379 under or overflow
3380 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003381static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003382{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003383 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003384
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003385 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003387 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003388 * INT64_MAX < 2^31. More than that will cause
3389 * exist with the overflow error
3390 */
3391 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003392 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003393 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003395 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396 nExponent--;
3397 }
3398
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003399 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003400 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003401 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3402 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003403 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003404 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003405 }
3406
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003407 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003409 return QCBOR_SUCCESS;
3410}
3411
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003412/*
3413 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3414 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003415static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3416{
3417 uint64_t uResult;
3418
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003419 // Take the absolute value of the mantissa and convert to unsigned.
3420 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003421 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3422
3423 // Do the exponentiation of the positive mantissa
3424 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3425 if(uReturn) {
3426 return uReturn;
3427 }
3428
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429
Laurence Lundblade983500d2020-05-14 11:49:34 -07003430 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3431 of INT64_MIN. This assumes two's compliment representation where
3432 INT64_MIN is one increment farther from 0 than INT64_MAX.
3433 Trying to write -INT64_MIN doesn't work to get this because the
3434 compiler tries to work with an int64_t which can't represent
3435 -INT64_MIN.
3436 */
3437 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3438
3439 // Error out if too large
3440 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003441 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3442 }
3443
3444 // Casts are safe because of checks above
3445 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3446
3447 return QCBOR_SUCCESS;
3448}
3449
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003450/*
3451 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3452 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003453static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3454{
3455 if(nMantissa < 0) {
3456 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3457 }
3458
3459 // Cast to unsigned is OK because of check for negative
3460 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3461 // Exponentiation is straight forward
3462 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3463}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003464#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3465
3466
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003467
3468
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003469#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003470
3471
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003472static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003474 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003475
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003476 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477 const uint8_t *pByte = BigNum.ptr;
3478 size_t uLen = BigNum.len;
3479 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003480 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003481 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003482 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003483 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484 }
3485
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003486 *pResult = uResult;
3487 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003488}
3489
Laurence Lundblade887add82020-05-17 05:50:34 -07003490static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003491{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003492 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003493}
3494
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003495static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003496{
3497 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003498 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3499 if(uError) {
3500 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003501 }
3502 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3503 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003504 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003505}
3506
3507
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003508static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003509{
3510 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003511 /* negaative int furthest from zero is INT64_MIN
3512 which is expressed as -INT64_MAX-1. The value of
3513 a negative bignum is -n-1, one further from zero
3514 than the positive bignum */
3515
3516 /* say INT64_MIN is -2; then INT64_MAX is 1.
3517 Then -n-1 <= INT64_MIN.
3518 Then -n -1 <= -INT64_MAX - 1
3519 THen n <= INT64_MAX. */
3520 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003521 if(uError) {
3522 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003523 }
3524 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003525 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003526 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003527 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003528 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003529}
3530
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003531
3532static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
3533{
3534 while((uInt & 0xff00000000000000UL) == 0) {
3535 uInt = uInt << 8;
3536 };
3537
3538 UsefulOutBuf UOB;
3539
3540 UsefulOutBuf_Init(&UOB, Buffer);
3541
3542 while(uInt) {
3543 const uint64_t xx = uInt & 0xff00000000000000UL;
3544 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
3545 uInt = uInt << 8;
3546 (void)xx;
3547 }
3548
3549 return UsefulOutBuf_OutUBuf(&UOB);
3550}
3551
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003552#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003553
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003554
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003555/*
3556Convert a integers and floats to an int64_t.
3557
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003558\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003559
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003560\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003561
3562\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3563
3564\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3565
3566*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003567static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003568{
3569 switch(pItem->uDataType) {
3570 // TODO: float when ifdefs are set
3571 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003572 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573 // TODO: what about under/overflow here?
3574 // Invokes the floating-point HW and/or compiler-added libraries
3575 feclearexcept(FE_ALL_EXCEPT);
3576 *pnValue = llround(pItem->val.dfnum);
3577 if(fetestexcept(FE_INVALID)) {
3578 // TODO: better error code
3579 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3580 }
3581 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003582 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583 }
3584 break;
3585
3586 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003587 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003588 *pnValue = pItem->val.int64;
3589 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003590 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003591 }
3592 break;
3593
3594 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003595 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003596 if(pItem->val.uint64 < INT64_MAX) {
3597 *pnValue = pItem->val.int64;
3598 } else {
3599 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3600 }
3601 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003602 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603 }
3604 break;
3605
3606 default:
3607 return QCBOR_ERR_UNEXPECTED_TYPE;
3608 }
3609 return QCBOR_SUCCESS;
3610}
3611
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003612
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003613void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003614 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003615 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003616 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003617{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003618 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003619 return;
3620 }
3621
Laurence Lundbladee6430642020-03-14 21:15:44 -07003622 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003623 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3624 if(uError) {
3625 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003626 return;
3627 }
3628
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003629 if(pItem) {
3630 *pItem = Item;
3631 }
3632
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003633 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003634}
3635
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003636
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003637void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3638 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003639 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640 int64_t *pnValue,
3641 QCBORItem *pItem)
3642{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003643 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003644 if(pMe->uLastError != QCBOR_SUCCESS) {
3645 return;
3646 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003647
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003648 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649}
3650
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003651
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3653 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003654 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003655 int64_t *pnValue,
3656 QCBORItem *pItem)
3657{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003658 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003659 if(pMe->uLastError != QCBOR_SUCCESS) {
3660 return;
3661 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003662
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003663 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003664}
3665
3666
3667
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003668/*
3669 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003670
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003671 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003672
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003673 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003674
3675 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3676
3677 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3678
3679 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003680static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003681{
3682 QCBORError uErr;
3683
3684 switch(pItem->uDataType) {
3685
3686 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003687 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003688 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003689 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003690 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003691 }
3692 break;
3693
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003694 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003695 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003696 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003697 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003698 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003699 }
3700 break;
3701
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003702#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3703 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003704 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003705 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3706 pItem->val.expAndMantissa.nExponent,
3707 pnValue,
3708 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003709 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003710 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003711 }
3712 break;
3713
3714 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003715 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003716 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3717 pItem->val.expAndMantissa.nExponent,
3718 pnValue,
3719 Exponentitate2);
3720 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003721 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003722 }
3723 break;
3724
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003726 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003727 int64_t nMantissa;
3728 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3729 if(uErr) {
3730 return uErr;
3731 }
3732 return ExponentiateNN(nMantissa,
3733 pItem->val.expAndMantissa.nExponent,
3734 pnValue,
3735 Exponentitate10);
3736 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003737 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003738 }
3739 break;
3740
3741 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003742 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003743 int64_t nMantissa;
3744 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3745 if(uErr) {
3746 return uErr;
3747 }
3748 return ExponentiateNN(nMantissa,
3749 pItem->val.expAndMantissa.nExponent,
3750 pnValue,
3751 Exponentitate10);
3752 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003753 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003754 }
3755 break;
3756
3757 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003758 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003759 int64_t nMantissa;
3760 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3761 if(uErr) {
3762 return uErr;
3763 }
3764 return ExponentiateNN(nMantissa,
3765 pItem->val.expAndMantissa.nExponent,
3766 pnValue,
3767 Exponentitate2);
3768 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003769 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003770 }
3771 break;
3772
3773 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003774 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003775 int64_t nMantissa;
3776 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3777 if(uErr) {
3778 return uErr;
3779 }
3780 return ExponentiateNN(nMantissa,
3781 pItem->val.expAndMantissa.nExponent,
3782 pnValue,
3783 Exponentitate2);
3784 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003785 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003786 }
3787 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003788#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3789
Laurence Lundbladee6430642020-03-14 21:15:44 -07003790
Laurence Lundbladec4537442020-04-14 18:53:22 -07003791 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003792 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003793}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003794
3795
Laurence Lundbladec4537442020-04-14 18:53:22 -07003796/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003797 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003798 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003799void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003800{
3801 QCBORItem Item;
3802
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003803 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003805 if(pMe->uLastError == QCBOR_SUCCESS) {
3806 // The above conversion succeeded
3807 return;
3808 }
3809
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003810 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003811 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003812 return;
3813 }
3814
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003815 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003816}
3817
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003818
3819/*
3820Public function, see header qcbor/qcbor_decode.h file
3821*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003822void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003823{
3824 QCBORItem Item;
3825
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003826 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003827
3828 if(pMe->uLastError == QCBOR_SUCCESS) {
3829 // The above conversion succeeded
3830 return;
3831 }
3832
3833 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3834 // The above conversion failed in a way that code below can't correct
3835 return;
3836 }
3837
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003838 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003839}
3840
3841
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003842/*
3843Public function, see header qcbor/qcbor_decode.h file
3844*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003845void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003846{
3847 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003848 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003849
3850 if(pMe->uLastError == QCBOR_SUCCESS) {
3851 // The above conversion succeeded
3852 return;
3853 }
3854
3855 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3856 // The above conversion failed in a way that code below can't correct
3857 return;
3858 }
3859
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003860 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003861}
3862
3863
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003864static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003865{
3866 switch(pItem->uDataType) {
3867 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003868 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003869 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003870 feclearexcept(FE_ALL_EXCEPT);
3871 double dRounded = round(pItem->val.dfnum);
3872 // TODO: over/underflow
3873 if(fetestexcept(FE_INVALID)) {
3874 // TODO: better error code
3875 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3876 } else if(isnan(dRounded)) {
3877 // TODO: better error code
3878 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3879 } else if(dRounded >= 0) {
3880 *puValue = (uint64_t)dRounded;
3881 } else {
3882 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3883 }
3884 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003885 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003886 }
3887 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003888
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003889 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003890 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003891 if(pItem->val.int64 >= 0) {
3892 *puValue = (uint64_t)pItem->val.int64;
3893 } else {
3894 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3895 }
3896 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003897 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003898 }
3899 break;
3900
3901 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003902 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003903 *puValue = pItem->val.uint64;
3904 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003905 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003906 }
3907 break;
3908
3909 default:
3910 return QCBOR_ERR_UNEXPECTED_TYPE;
3911 }
3912 return QCBOR_SUCCESS;
3913}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003914
3915
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003916void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003917 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003918 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003919 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003920{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003921 if(pMe->uLastError != QCBOR_SUCCESS) {
3922 return;
3923 }
3924
Laurence Lundbladec4537442020-04-14 18:53:22 -07003925 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003926
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003927 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3928 if(uError) {
3929 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003930 return;
3931 }
3932
Laurence Lundbladea826c502020-05-10 21:07:00 -07003933 if(pItem) {
3934 *pItem = Item;
3935 }
3936
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003937 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003938}
3939
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003940
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003941
3942
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003943void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3944 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003945 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003946 uint64_t *puValue,
3947 QCBORItem *pItem)
3948{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003949 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003950 if(pMe->uLastError != QCBOR_SUCCESS) {
3951 return;
3952 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003953
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003954 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003955}
3956
3957
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003958void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003959 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003960 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003961 uint64_t *puValue,
3962 QCBORItem *pItem)
3963{
3964 if(pMe->uLastError != QCBOR_SUCCESS) {
3965 return;
3966 }
3967
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003968 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003969 if(pMe->uLastError != QCBOR_SUCCESS) {
3970 return;
3971 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003972
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003973 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974}
3975
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003976/*
3977 Public function, see header qcbor/qcbor_decode.h file
3978*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003979static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003980{
3981 QCBORError uErr;
3982
3983 switch(pItem->uDataType) {
3984
3985 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003986 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003987 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3988 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003989 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003990 }
3991 break;
3992
3993 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003994 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003995 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3996 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003997 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003998 }
3999 break;
4000
4001#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4002
4003 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004004 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004005 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4006 pItem->val.expAndMantissa.nExponent,
4007 puValue,
4008 Exponentitate10);
4009 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004011 }
4012 break;
4013
4014 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004015 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004016 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4017 pItem->val.expAndMantissa.nExponent,
4018 puValue,
4019 Exponentitate2);
4020 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004021 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004022 }
4023 break;
4024
4025 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004026 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004027 // TODO: Would be better to convert to unsigned
4028 int64_t nMantissa;
4029 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4030 if(uErr != QCBOR_SUCCESS) {
4031 return uErr;
4032 }
4033 return ExponentitateNU(nMantissa,
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_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004043 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4045 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004047 }
4048 break;
4049
4050 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004051 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004052 // TODO: Would be better to convert to unsigned
4053 int64_t nMantissa;
4054 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4055 if(uErr != QCBOR_SUCCESS) {
4056 return uErr;
4057 }
4058 return ExponentitateNU(nMantissa,
4059 pItem->val.expAndMantissa.nExponent,
4060 puValue,
4061 Exponentitate2);
4062 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004063 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004064 }
4065 break;
4066
4067 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004069 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4070 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004072 }
4073 break;
4074#endif
4075 default:
4076 return QCBOR_ERR_UNEXPECTED_TYPE;
4077 }
4078}
4079
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004080/*
4081 Public function, see header qcbor/qcbor_decode.h file
4082*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004083void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004084{
4085 QCBORItem Item;
4086
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004087 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004088
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004089 if(pMe->uLastError == QCBOR_SUCCESS) {
4090 // The above conversion succeeded
4091 return;
4092 }
4093
4094 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4095 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004096 return;
4097 }
4098
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004099 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004100}
4101
Laurence Lundbladec4537442020-04-14 18:53:22 -07004102
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004103/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004104 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004105*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004107{
4108 QCBORItem Item;
4109
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004110 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004111
4112 if(pMe->uLastError == QCBOR_SUCCESS) {
4113 // The above conversion succeeded
4114 return;
4115 }
4116
4117 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4118 // The above conversion failed in a way that code below can't correct
4119 return;
4120 }
4121
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004123}
4124
4125
4126/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004127 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004128*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004129void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004130{
4131 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004132 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004133
4134 if(pMe->uLastError == QCBOR_SUCCESS) {
4135 // The above conversion succeeded
4136 return;
4137 }
4138
4139 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4140 // The above conversion failed in a way that code below can't correct
4141 return;
4142 }
4143
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004145}
4146
4147
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004148static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149{
4150 switch(pItem->uDataType) {
4151 // TODO: float when ifdefs are set
4152 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4154 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004155 *pdValue = pItem->val.dfnum;
4156 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004157 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004158 }
4159 }
4160 break;
4161
4162 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004163 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004164 // TODO: how does this work?
4165 *pdValue = (double)pItem->val.int64;
4166
4167 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004168 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004169 }
4170 break;
4171
4172 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004173 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004174 *pdValue = (double)pItem->val.uint64;
4175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177 }
4178 break;
4179
4180 default:
4181 return QCBOR_ERR_UNEXPECTED_TYPE;
4182 }
4183
4184 return QCBOR_SUCCESS;
4185}
4186
4187
4188
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004189void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004190 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004191 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004192 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004193{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004194 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004195 return;
4196 }
4197
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004198 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004199
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004200 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004201 if(uError) {
4202 pMe->uLastError = (uint8_t)uError;
4203 return;
4204 }
4205
4206 if(pItem) {
4207 *pItem = Item;
4208 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004209
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004210 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004211}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004212
Laurence Lundbladec4537442020-04-14 18:53:22 -07004213
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004214void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4215 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217 double *pdValue,
4218 QCBORItem *pItem)
4219{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004220 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004221 if(pMe->uLastError != QCBOR_SUCCESS) {
4222 return;
4223 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004224
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004225 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004226}
4227
4228void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4229 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004230 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004231 double *pdValue,
4232 QCBORItem *pItem)
4233{
4234 if(pMe->uLastError != QCBOR_SUCCESS) {
4235 return;
4236 }
4237
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004238 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004239 if(pMe->uLastError != QCBOR_SUCCESS) {
4240 return;
4241 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004242
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004244}
4245
4246
4247
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004248static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4249{
4250 double dResult;
4251
4252 dResult = 0.0;
4253 const uint8_t *pByte = BigNum.ptr;
4254 size_t uLen = BigNum.len;
4255 /* This will overflow and become the float value INFINITY if the number
4256 is too large to fit. No error will be logged.
4257 TODO: should an error be logged? */
4258 while(uLen--) {
4259 dResult = (dResult * 256.0) + (double)*pByte++;
4260 }
4261
4262 return dResult;
4263}
4264
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004265static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004266{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004267 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004268 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4269
4270 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004271 switch(pItem->uDataType) {
4272 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004273
4274#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004275 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004276 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004277 // TODO: rounding and overflow errors
4278 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4279 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4280 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004281 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004282 }
4283 break;
4284
4285 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004286 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004287 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4288 exp2((double)pItem->val.expAndMantissa.nExponent);
4289 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004290 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004291 }
4292 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004293#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004294
4295 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004296 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004297 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4298 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004299 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004300 }
4301 break;
4302
4303 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004304 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004305 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004306 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004307 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004308 }
4309 break;
4310
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004311#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004312 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004313 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004314 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4315 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4316 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004317 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004318 }
4319 break;
4320
4321 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004322 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004323 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4324 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4325 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004326 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004327 }
4328 break;
4329
4330 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004331 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004332 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4333 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4334 } 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
4339 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004340 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004341 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004342 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4343 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004344 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004345 }
4346 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004347#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4348
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004349
4350 default:
4351 return QCBOR_ERR_UNEXPECTED_TYPE;
4352 }
4353
4354 return QCBOR_SUCCESS;
4355}
4356
4357
4358/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004359 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004361void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004362{
4363
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004364 QCBORItem Item;
4365
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004366 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004367
4368 if(pMe->uLastError == QCBOR_SUCCESS) {
4369 // The above conversion succeeded
4370 return;
4371 }
4372
4373 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4374 // The above conversion failed in a way that code below can't correct
4375 return;
4376 }
4377
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004378 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004379}
4380
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004381
4382/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004383 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004384*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004385void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004386{
4387 QCBORItem Item;
4388
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004389 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004390
4391 if(pMe->uLastError == QCBOR_SUCCESS) {
4392 // The above conversion succeeded
4393 return;
4394 }
4395
4396 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4397 // The above conversion failed in a way that code below can't correct
4398 return;
4399 }
4400
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004401 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402}
4403
4404
4405/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004406 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004408void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409{
4410 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004411 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004412
4413 if(pMe->uLastError == QCBOR_SUCCESS) {
4414 // The above conversion succeeded
4415 return;
4416 }
4417
4418 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4419 // The above conversion failed in a way that code below can't correct
4420 return;
4421 }
4422
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004425
4426
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004427
4428
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004429#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004430static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4431 TagSpecification TagSpec,
4432 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004433{
4434 QCBORError uErr;
4435 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004436 while(1) {
4437 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4438 if(uErr != QCBOR_SUCCESS) {
4439 goto Done;
4440 }
4441
4442 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4443 break; // Successful exit. Moving on to finish decoding.
4444 }
4445
4446 // The item is an array, which means an undecoded
4447 // mantissa and exponent, so decode it. It will then
4448 // have a different type and exit the loop if.
4449 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4450 if(uErr != QCBOR_SUCCESS) {
4451 goto Done;
4452 }
4453
4454 // Second time around, the type must match.
4455 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
4456 }
4457Done:
4458 return uErr;
4459}
4460
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004461
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004462static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004463 TagSpecification TagSpec,
4464 QCBORItem *pItem,
4465 int64_t *pnMantissa,
4466 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004467{
4468 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004469
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004470 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004471 if(uErr != QCBOR_SUCCESS) {
4472 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004473 }
4474
4475 switch (pItem->uDataType) {
4476
4477 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004478 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004479 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4480 *pnExponent = pItem->val.expAndMantissa.nExponent;
4481 break;
4482
4483 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004484 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004485 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004486 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004487 break;
4488
4489 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004490 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004491 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004492 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004493 break;
4494
4495 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004496 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004497 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004498
4499 Done:
4500 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004501}
4502
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004503
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004504static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004505 TagSpecification TagSpec,
4506 QCBORItem *pItem,
4507 UsefulBuf BufferForMantissa,
4508 UsefulBufC *pMantissa,
4509 bool *pbIsNegative,
4510 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004511{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004512 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004513
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004514 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004515 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004516 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004517 }
4518
4519 uint64_t uMantissa;
4520
4521 switch (pItem->uDataType) {
4522
4523 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004524 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004525 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4526 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4527 *pbIsNegative = false;
4528 } else {
4529 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4530 *pbIsNegative = true;
4531 }
4532 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4533 *pnExponent = pItem->val.expAndMantissa.nExponent;
4534 break;
4535
4536 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004537 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004538 *pnExponent = pItem->val.expAndMantissa.nExponent;
4539 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4540 *pbIsNegative = false;
4541 break;
4542
4543 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004544 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004545 *pnExponent = pItem->val.expAndMantissa.nExponent;
4546 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4547 *pbIsNegative = true;
4548 break;
4549
4550 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004551 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004552 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004553
4554Done:
4555 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004556}
4557
4558
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004559/*
4560 Public function, see header qcbor/qcbor_decode.h file
4561*/
4562void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4563 uint8_t uTagRequirement,
4564 int64_t *pnMantissa,
4565 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004566{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004567 if(pMe->uLastError != QCBOR_SUCCESS) {
4568 return;
4569 }
4570
4571 QCBORItem Item;
4572 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4573 if(uError) {
4574 pMe->uLastError = (uint8_t)uError;
4575 return;
4576 }
4577
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004578 const TagSpecification TagSpec =
4579 {
4580 uTagRequirement,
4581 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4582 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4583 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004584
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004585 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004586}
4587
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004588
4589/*
4590 Public function, see header qcbor/qcbor_decode.h file
4591*/
4592void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004593 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004594 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004595 int64_t *pnMantissa,
4596 int64_t *pnExponent)
4597{
4598 if(pMe->uLastError != QCBOR_SUCCESS) {
4599 return;
4600 }
4601
4602 QCBORItem Item;
4603 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4604
4605 const TagSpecification TagSpec =
4606 {
4607 uTagRequirement,
4608 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4609 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4610 };
4611
4612 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4613}
4614
4615
4616/*
4617 Public function, see header qcbor/qcbor_decode.h file
4618*/
4619void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004620 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004621 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004622 int64_t *pnMantissa,
4623 int64_t *pnExponent)
4624{
4625 if(pMe->uLastError != QCBOR_SUCCESS) {
4626 return;
4627 }
4628
4629 QCBORItem Item;
4630 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4631
4632 const TagSpecification TagSpec =
4633 {
4634 uTagRequirement,
4635 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4636 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4637 };
4638
4639 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4640}
4641
4642
4643/*
4644 Public function, see header qcbor/qcbor_decode.h file
4645*/
4646void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4647 uint8_t uTagRequirement,
4648 UsefulBuf MantissaBuffer,
4649 UsefulBufC *pMantissa,
4650 bool *pbMantissaIsNegative,
4651 int64_t *pnExponent)
4652{
4653 if(pMe->uLastError != QCBOR_SUCCESS) {
4654 return;
4655 }
4656
4657 QCBORItem Item;
4658 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4659 if(uError) {
4660 pMe->uLastError = (uint8_t)uError;
4661 return;
4662 }
4663
4664 const TagSpecification TagSpec =
4665 {
4666 uTagRequirement,
4667 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4668 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4669 };
4670
4671 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4672}
4673
4674
4675/*
4676 Public function, see header qcbor/qcbor_decode.h file
4677*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004678void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004679 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004680 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004681 UsefulBuf BufferForMantissa,
4682 UsefulBufC *pMantissa,
4683 bool *pbIsNegative,
4684 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004685{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004686 if(pMe->uLastError != QCBOR_SUCCESS) {
4687 return;
4688 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004689
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004690 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004691 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004692 if(pMe->uLastError != QCBOR_SUCCESS) {
4693 return;
4694 }
4695
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004696 const TagSpecification TagSpec =
4697 {
4698 uTagRequirement,
4699 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4700 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4701 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004702
4703 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004704}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004705
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004706
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004707/*
4708 Public function, see header qcbor/qcbor_decode.h file
4709*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004710void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004711 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004712 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004713 UsefulBuf BufferForMantissa,
4714 UsefulBufC *pMantissa,
4715 bool *pbIsNegative,
4716 int64_t *pnExponent)
4717{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004718 if(pMe->uLastError != QCBOR_SUCCESS) {
4719 return;
4720 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004721
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004722 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004723 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4724 if(pMe->uLastError != QCBOR_SUCCESS) {
4725 return;
4726 }
4727
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004728 const TagSpecification TagSpec =
4729 {
4730 uTagRequirement,
4731 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4732 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4733 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004734
4735 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4736}
4737
4738
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004739/*
4740 Public function, see header qcbor/qcbor_decode.h file
4741*/
4742void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
4743 uint8_t uTagRequirement,
4744 int64_t *pnMantissa,
4745 int64_t *pnExponent)
4746{
4747 if(pMe->uLastError != QCBOR_SUCCESS) {
4748 return;
4749 }
4750
4751 QCBORItem Item;
4752 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4753 if(uError) {
4754 pMe->uLastError = (uint8_t)uError;
4755 return;
4756 }
4757 const TagSpecification TagSpec =
4758 {
4759 uTagRequirement,
4760 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4761 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4762 };
4763
4764 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4765}
4766
4767
4768/*
4769 Public function, see header qcbor/qcbor_decode.h file
4770*/
4771void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004772 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004773 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004774 int64_t *pnMantissa,
4775 int64_t *pnExponent)
4776{
4777 if(pMe->uLastError != QCBOR_SUCCESS) {
4778 return;
4779 }
4780
4781 QCBORItem Item;
4782 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4783 if(pMe->uLastError != QCBOR_SUCCESS) {
4784 return;
4785 }
4786
4787 const TagSpecification TagSpec =
4788 {
4789 uTagRequirement,
4790 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4791 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4792 };
4793
4794 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4795}
4796
4797
4798/*
4799 Public function, see header qcbor/qcbor_decode.h file
4800*/
4801void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004802 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004803 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004804 int64_t *pnMantissa,
4805 int64_t *pnExponent)
4806{
4807 if(pMe->uLastError != QCBOR_SUCCESS) {
4808 return;
4809 }
4810
4811 QCBORItem Item;
4812 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4813 if(pMe->uLastError != QCBOR_SUCCESS) {
4814 return;
4815 }
4816
4817 const TagSpecification TagSpec =
4818 {
4819 uTagRequirement,
4820 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4821 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4822 };
4823
4824 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4825}
4826
4827
4828/*
4829 Public function, see header qcbor/qcbor_decode.h file
4830*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004831void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
4832 uint8_t uTagRequirement,
4833 UsefulBuf MantissaBuffer,
4834 UsefulBufC *pMantissa,
4835 bool *pbMantissaIsNegative,
4836 int64_t *pnExponent)
4837{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004838 if(pMe->uLastError != QCBOR_SUCCESS) {
4839 return;
4840 }
4841
4842 QCBORItem Item;
4843 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4844 if(uError) {
4845 pMe->uLastError = (uint8_t)uError;
4846 return;
4847 }
4848
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004849 const TagSpecification TagSpec =
4850 {
4851 uTagRequirement,
4852 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4853 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4854 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004855
4856 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004857}
4858
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004859
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004860/*
4861 Public function, see header qcbor/qcbor_decode.h file
4862*/
4863void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004864 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004865 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004866 UsefulBuf BufferForMantissa,
4867 UsefulBufC *pMantissa,
4868 bool *pbIsNegative,
4869 int64_t *pnExponent)
4870{
4871 if(pMe->uLastError != QCBOR_SUCCESS) {
4872 return;
4873 }
4874
4875 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004876 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4877 if(pMe->uLastError != QCBOR_SUCCESS) {
4878 return;
4879 }
4880
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004881 const TagSpecification TagSpec =
4882 {
4883 uTagRequirement,
4884 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4885 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4886 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004887
4888 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4889}
4890
4891
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004892/*
4893 Public function, see header qcbor/qcbor_decode.h file
4894*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004895void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004896 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004897 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004898 UsefulBuf BufferForMantissa,
4899 UsefulBufC *pMantissa,
4900 bool *pbIsNegative,
4901 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004902{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004903 if(pMe->uLastError != QCBOR_SUCCESS) {
4904 return;
4905 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004906
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004907 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004908 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4909 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004910 return;
4911 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004912
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004913 const TagSpecification TagSpec =
4914 {
4915 uTagRequirement,
4916 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4917 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4918 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004919
4920 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004921}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004922
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004923#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */