blob: bf6e8acb00c260fcc7475187abba8f4afeff6c49 [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 Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundblade02625d42020-06-25 14:41:41 -070046inline static bool
47// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
48QCBORItem_IsMapOrArray(const QCBORItem *pMe)
49{
50 const uint8_t uDataType = pMe->uDataType;
51 return uDataType == QCBOR_TYPE_MAP ||
52 uDataType == QCBOR_TYPE_ARRAY ||
53 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
54}
55
56inline static bool
57QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
58{
59 if(!QCBORItem_IsMapOrArray(pMe)){
60 return false;
61 }
62
63 if(pMe->val.uCount != 0) {
64 return false;
65 }
66 return true;
67}
68
69inline static bool
70QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
77 return false;
78 }
79 return true;
80}
81
82
Laurence Lundbladeee851742020-01-08 08:37:05 -080083/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070084 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080085 ===========================================================================*/
86
Laurence Lundblade9c905e82020-04-25 11:31:38 -070087/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070088 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
89 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070090
Laurence Lundblade9c905e82020-04-25 11:31:38 -070091
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092
Laurence Lundblade9c905e82020-04-25 11:31:38 -070093 */
94
Laurence Lundblade24d509a2020-06-06 18:43:15 -070095
96inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -070097DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -070098{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070099 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700100 /*
101 Limit in DecodeNesting_Descend against more than
102 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
103 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700104 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105}
106
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700107
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700108inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700109DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700111 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112 /*
113 Limit in DecodeNesting_Descend against more than
114 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
115 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700116 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700117}
118
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700119
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120static inline size_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700121DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700122{
123 return pNesting->pCurrentBounded->u.ma.uStartOffset;
124}
125
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700126
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700128DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700129{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700130 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700131 return true;
132 } else {
133 return false;
134 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135}
136
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700137
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700138inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700139DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700140{
141 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700142 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143 return false;
144 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700145 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700146 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147 return false;
148 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700150 return true;
151}
152
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700153
Laurence Lundblade642282a2020-06-23 12:00:33 -0700154inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700155DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700156{
157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700159 return true;
160 }
161 return false;
162}
163
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700164
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700165inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166{
167 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
168 return true;
169 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700170 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700171 return true;
172 }
173 return false;
174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178{
179 // Should be only called on maps and arrays
180 // TODO: check this cast, maybe give an error?
181 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
182}
183
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700184
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700185inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700186{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700187 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700188}
189
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700190
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700191inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700192DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700193{
194 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700195 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700196 return false;
197 }
198 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700199 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700200 return false;
201 }
202 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700203 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700204 return false;
205 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700206 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700207 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700208 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700209 return false;
210 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700211 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700212 return true;
213}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700216inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700217DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700220 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
221 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700222 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700223 return false;
224 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700225}
226
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700227
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700228inline static bool
229DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700230{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700231 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
232 return true;
233 } else {
234 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700235 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700236}
237
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700239inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700241{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700242 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700243 return false;
244 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700245
246 if(pNesting->pCurrentBounded->uLevelType != uType) {
247 return false;
248 }
249
250 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700251}
252
Laurence Lundblade02625d42020-06-25 14:41:41 -0700253
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700254inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700255DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700256{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700257 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700259}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700260
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700262inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700263DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
264{
265 // Only call on a defnite length array / map
266 pNesting->pCurrent->u.ma.uCountCursor++;
267}
268
269
270inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700271DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
272{
273 pNesting->pCurrent--;
274}
275
Laurence Lundblade02625d42020-06-25 14:41:41 -0700276
277static QCBORError
278DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
279{
280 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
283 }
284
285 // The actual descend
286 pNesting->pCurrent++;
287
288 pNesting->pCurrent->uLevelType = uType;
289
290 return QCBOR_SUCCESS;
291}
292
293
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700294inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700295DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700296{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700297 /*
298 Should only be called on map/array.
299
300 Have descended into this before this is called. The job here is
301 just to mark it in bounded mode.
302 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700303 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700304 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700305}
306
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700307
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700308inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700310 uint8_t uQCBORType,
311 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700312{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700314
315 if(uCount == 0) {
316 // Nothing to do for empty definite lenth arrays. They are just are
317 // effectively the same as an item that is not a map or array
318 goto Done;
319 // Empty indefinite length maps and arrays are handled elsewhere
320 }
321
322 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
324 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
325 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700326 goto Done;
327 }
328
Laurence Lundblade02625d42020-06-25 14:41:41 -0700329 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
330 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700331 goto Done;
332 }
333
Laurence Lundblade02625d42020-06-25 14:41:41 -0700334 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700335 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
336 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700337
338 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339
340Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700341 return uError;;
342}
343
344
345static inline void
346DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
347{
348 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
349}
350
351
352static inline void
353DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
354{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700355 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 pNesting->pCurrentBounded--;
357 if(DecodeNesting_IsCurrentBounded(pNesting)) {
358 break;
359 }
360 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700361}
362
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700363static inline void
364DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
365{
366 pNesting->pCurrent = pNesting->pCurrentBounded;
367}
368
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700369
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700370inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700371DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
372 size_t uEndOffset,
373 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700374{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700376
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
378 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700379 goto Done;
380 }
381
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 // Fill in the new byte string level
383 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700385 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700386
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700388 pNesting->pCurrentBounded = pNesting->pCurrent;
389
390Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700391 return uError;;
392}
393
Laurence Lundbladed0304932020-06-27 10:59:38 -0700394
395static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700396DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397{
398 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700399}
400
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700401
Laurence Lundbladeee851742020-01-08 08:37:05 -0800402inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700403DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700404{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700406 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
407 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700408}
409
410
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700411inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700413{
414 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700415 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700417}
418
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700421DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700422{
423 *pNesting = *pSave;
424}
425
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700426
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700428DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429{
430 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
431}
432
433
Laurence Lundblade02625d42020-06-25 14:41:41 -0700434static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700435DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700436{
437 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
438}
439
440
Laurence Lundblade02625d42020-06-25 14:41:41 -0700441#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700442
443const char *TypeStr(uint8_t type)
444{
445 switch(type) {
446 case QCBOR_TYPE_MAP: return " map";
447 case QCBOR_TYPE_ARRAY: return "array";
448 case QCBOR_TYPE_BYTE_STRING: return " bstr";
449 default: return " --- ";
450 }
451}
452
453static char buf[20]; // Not thread safe, but that is OK
454const char *CountString(uint16_t uCount, uint16_t uTotal)
455{
456 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
457 strcpy(buf, "indefinite");
458 } else {
459 sprintf(buf, "%d/%d", uCount, uTotal);
460 }
461 return buf;
462}
463
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700464
Laurence Lundblade02625d42020-06-25 14:41:41 -0700465void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700466{
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700467 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700468 szName,
469 (uint32_t)pBuf->cursor,
470 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700471
472 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700473 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475 break;
476 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700477
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700478 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700479 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700480 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700481 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700482
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700483 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700484 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700485 pNesting->pLevels[i].u.bs.uEndOfBstr,
486 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700487
488 } else {
489 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700490 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
491 pNesting->pLevels[i].u.ma.uCountTotal));
492 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
493 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 }
495 }
496
497 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700498 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700499 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700500}
501
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700502
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700503
Laurence Lundbladeee851742020-01-08 08:37:05 -0800504/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800505 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
506
507 The following four functions are pretty wrappers for invocation of
508 the string allocator supplied by the caller.
509
Laurence Lundbladeee851742020-01-08 08:37:05 -0800510 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512static inline void
513StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514{
515 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
516}
517
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518// StringAllocator_Reallocate called with pMem NULL is
519// equal to StringAllocator_Allocate()
520static inline UsefulBuf
521StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
522 void *pMem,
523 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528static inline UsefulBuf
529StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530{
531 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
532}
533
Laurence Lundbladeee851742020-01-08 08:37:05 -0800534static inline void
535StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800536{
537 if(pMe->pfAllocator) {
538 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
539 }
540}
541
542
543
Laurence Lundbladeee851742020-01-08 08:37:05 -0800544/*===========================================================================
545 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700546
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800547 See qcbor/qcbor_decode.h for definition of the object
548 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800549 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700550/*
551 Public function, see header file
552 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800553void QCBORDecode_Init(QCBORDecodeContext *me,
554 UsefulBufC EncodedCBOR,
555 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556{
557 memset(me, 0, sizeof(QCBORDecodeContext));
558 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800559 // Don't bother with error check on decode mode. If a bad value is
560 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700561 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700562 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700563 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700564 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700565 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700566}
567
568
569/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700570 Public function, see header file
571 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800572void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
573 QCBORStringAllocate pfAllocateFunction,
574 void *pAllocateContext,
575 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700576{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800577 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
578 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
579 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580}
581
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582
583/*
584 Public function, see header file
585 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700586void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700588{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700589 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700590 (void)pMe;
591 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700592}
593
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700594
595/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 This decodes the fundamental part of a CBOR data item, the type and
597 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800598
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 This does the network->host byte order conversion. The conversion
602 here also results in the conversion for floats in addition to that
603 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700605 This returns:
606 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800608 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800609 tags and floats and length for strings and arrays
610
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800612 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800613
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 The int type is preferred to uint8_t for some variables as this
615 avoids integer promotions, can reduce code size and makes
616 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
619 int *pnMajorType,
620 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700623 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800624
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800626 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800629 const int nTmpMajorType = nInitialByte >> 5;
630 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800631
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 // Where the number or argument accumulates
633 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800635 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700636 // Need to get 1,2,4 or 8 additional argument bytes. Map
637 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800638 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800639
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800640 // Loop getting all the bytes in the argument
641 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800642 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800643 // This shift and add gives the endian conversion
644 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
645 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800647 // The reserved and thus-far unused additional info values
648 nReturn = QCBOR_ERR_UNSUPPORTED;
649 goto Done;
650 } else {
651 // Less than 24, additional info is argument or 31, an indefinite length
652 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800653 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 if(UsefulInputBuf_GetError(pUInBuf)) {
657 nReturn = QCBOR_ERR_HIT_END;
658 goto Done;
659 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800660
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700661 // All successful if we got here.
662 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800664 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800665 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667Done:
668 return nReturn;
669}
670
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800673 CBOR doesn't explicitly specify two's compliment for integers but all
674 CPUs use it these days and the test vectors in the RFC are so. All
675 integers in the CBOR structure are positive and the major type
676 indicates positive or negative. CBOR can express positive integers
677 up to 2^x - 1 where x is the number of bits and negative integers
678 down to 2^x. Note that negative numbers can be one more away from
679 zero than positive. Stdint, as far as I can tell, uses two's
680 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800683 used carefully here, and in particular why it isn't used in the interface.
684 Also see
685 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
686
687 Int is used for values that need less than 16-bits and would be subject
688 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800690inline static QCBORError
691DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700693 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
696 if (uNumber <= INT64_MAX) {
697 pDecodedItem->val.int64 = (int64_t)uNumber;
698 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700 } else {
701 pDecodedItem->val.uint64 = uNumber;
702 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 }
705 } else {
706 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800707 // CBOR's representation of negative numbers lines up with the
708 // two-compliment representation. A negative integer has one
709 // more in range than a positive integer. INT64_MIN is
710 // equal to (-INT64_MAX) - 1.
711 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 } else {
715 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000716 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 nReturn = QCBOR_ERR_INT_OVERFLOW;
718 }
719 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 return nReturn;
722}
723
724// Make sure #define value line up as DecodeSimple counts on this.
725#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
726#error QCBOR_TYPE_FALSE macro value wrong
727#endif
728
729#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
730#error QCBOR_TYPE_TRUE macro value wrong
731#endif
732
733#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
734#error QCBOR_TYPE_NULL macro value wrong
735#endif
736
737#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
738#error QCBOR_TYPE_UNDEF macro value wrong
739#endif
740
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700741#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
742#error QCBOR_TYPE_BREAK macro value wrong
743#endif
744
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
746#error QCBOR_TYPE_DOUBLE macro value wrong
747#endif
748
749#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
750#error QCBOR_TYPE_FLOAT macro value wrong
751#endif
752
753/*
754 Decode true, false, floats, break...
755 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800756inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800757DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700758{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700759 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800760
Laurence Lundbladeee851742020-01-08 08:37:05 -0800761 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800762 // above make sure uAdditionalInfo values line up with uDataType values.
763 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
764 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800765
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800767 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
768 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700770 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700771 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
772 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700773 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700774 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700775 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
776 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700777 break;
778 case DOUBLE_PREC_FLOAT:
779 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700780 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700781 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 case CBOR_SIMPLEV_FALSE: // 20
784 case CBOR_SIMPLEV_TRUE: // 21
785 case CBOR_SIMPLEV_NULL: // 22
786 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700787 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 case CBOR_SIMPLEV_ONEBYTE: // 24
791 if(uNumber <= CBOR_SIMPLE_BREAK) {
792 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700793 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700794 goto Done;
795 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800796 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799 default: // 0-19
800 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801 /*
802 DecodeTypeAndNumber will make uNumber equal to
803 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
804 safe because the 2, 4 and 8 byte lengths of uNumber are in
805 the double/float cases above
806 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 pDecodedItem->val.uSimple = (uint8_t)uNumber;
808 break;
809 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811Done:
812 return nReturn;
813}
814
815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530817 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800819inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
820 int nMajorType,
821 uint64_t uStrLen,
822 UsefulInputBuf *pUInBuf,
823 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700824{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700825 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800827 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
828 // This check makes the casts to size_t below safe.
829
830 // 4 bytes less than the largest sizeof() so this can be tested by
831 // putting a SIZE_MAX length in the CBOR test input (no one will
832 // care the limit on strings is 4 bytes shorter).
833 if(uStrLen > SIZE_MAX-4) {
834 nReturn = QCBOR_ERR_STRING_TOO_LONG;
835 goto Done;
836 }
837
838 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530839 if(UsefulBuf_IsNULLC(Bytes)) {
840 // Failed to get the bytes for this string item
841 nReturn = QCBOR_ERR_HIT_END;
842 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530844
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800845 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530846 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800847 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530848 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700849 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530850 goto Done;
851 }
852 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800853 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530854 } else {
855 // Normal case with no string allocator
856 pDecodedItem->val.string = Bytes;
857 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800858 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800859 // Cast because ternary operator causes promotion to integer
860 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
861 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530863Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 return nReturn;
865}
866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800868
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700869
870
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871
872
Laurence Lundbladeee851742020-01-08 08:37:05 -0800873// Make sure the constants align as this is assumed by
874// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700875#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
876#error QCBOR_TYPE_ARRAY value not lined up with major type
877#endif
878#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
879#error QCBOR_TYPE_MAP value not lined up with major type
880#endif
881
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700882/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800883 This gets a single data item and decodes it including preceding
884 optional tagging. This does not deal with arrays and maps and nesting
885 except to decode the data item introducing them. Arrays and maps are
886 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800887
Laurence Lundbladeee851742020-01-08 08:37:05 -0800888 Errors detected here include: an array that is too long to decode,
889 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700890 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800891static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
892 QCBORItem *pDecodedItem,
893 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700895 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundbladeee851742020-01-08 08:37:05 -0800897 /*
898 Get the major type and the number. Number could be length of more
899 bytes or the value depending on the major type nAdditionalInfo is
900 an encoding of the length of the uNumber and is needed to decode
901 floats and doubles
902 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800903 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800905 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700907 memset(pDecodedItem, 0, sizeof(QCBORItem));
908
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800909 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800910
Laurence Lundbladeee851742020-01-08 08:37:05 -0800911 // Error out here if we got into trouble on the type and number. The
912 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700913 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700915 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917 // At this point the major type and the value are valid. We've got
918 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800919 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
921 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800922 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700923 nReturn = QCBOR_ERR_BAD_INT;
924 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800925 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700926 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700929 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
930 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
932 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
933 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
934 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530935 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938 }
939 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700941 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
942 case CBOR_MAJOR_TYPE_MAP: // Major type 5
943 // Record the number of items in the array or map
944 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
945 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
946 goto Done;
947 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800948 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700949 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 // type conversion OK because of check above
952 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800954 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
956 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700959 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800960 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700961 nReturn = QCBOR_ERR_BAD_INT;
962 } else {
963 pDecodedItem->val.uTagV = uNumber;
964 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
965 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700966 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800967
Laurence Lundbladeee851742020-01-08 08:37:05 -0800968 case CBOR_MAJOR_TYPE_SIMPLE:
969 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800970 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700971 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladeee851742020-01-08 08:37:05 -0800973 default:
974 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 nReturn = QCBOR_ERR_UNSUPPORTED;
976 break;
977 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979Done:
980 return nReturn;
981}
982
983
984
985/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800986 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 individual chunk items together into one QCBORItem using the string
988 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800989
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530990 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992static inline QCBORError
993GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700995 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700996
997 // Get pointer to string allocator. First use is to pass it to
998 // GetNext_Item() when option is set to allocate for *every* string.
999 // Second use here is to allocate space to coallese indefinite
1000 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001001 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1002 &(me->StringAllocator) :
1003 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001004
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001005 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001006 nReturn = GetNext_Item(&(me->InBuf),
1007 pDecodedItem,
1008 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 if(nReturn) {
1010 goto Done;
1011 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001013 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301014 // code in this function from here down can be eliminated. Run tests, except
1015 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001016
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001017 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001018 const uint8_t uStringType = pDecodedItem->uDataType;
1019 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 goto Done; // no need to do any work here on non-string types
1021 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001023 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301024 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001025 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301028 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001029 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1031 goto Done;
1032 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001033
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001034 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001035 UsefulBufC FullString = NULLUsefulBufC;
1036
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001038 // Get item for next chunk
1039 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001040 // NULL string allocator passed here. Do not need to allocate
1041 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001042 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001043 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001044 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001046
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301047 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001048 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001049 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301051 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052 break;
1053 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001055 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301056 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001057 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001058 if(StringChunkItem.uDataType != uStringType ||
1059 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001060 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 break;
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301064 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001065 // The first time throurgh FullString.ptr is NULL and this is
1066 // equivalent to StringAllocator_Allocate()
1067 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1068 UNCONST_POINTER(FullString.ptr),
1069 FullString.len + StringChunkItem.val.string.len);
1070
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301072 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001073 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074 break;
1075 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001077 // Copy new string chunk at the end of string so far.
1078 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001079 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001080
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001081 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1082 // Getting the item failed, clean up the allocated memory
1083 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001086Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001087 return nReturn;
1088}
1089
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001090
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001091static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1092 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001093 return uTagVal;
1094 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001095 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001096 return me->auMappedTags[x];
1097 }
1098}
1099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001100/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001101 Gets all optional tag data items preceding a data item that is not an
1102 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001103 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001105GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001106{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001107 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001108
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001109 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1110 CBOR_TAG_INVALID16,
1111 CBOR_TAG_INVALID16,
1112 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001113
Laurence Lundblade59289e52019-12-30 13:44:37 -08001114 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001115 for(;;) {
1116 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001117 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001118 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001121 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1122 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001123 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001124 break;
1125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001126
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001127 // Is there room for the tag in the tags list?
1128 size_t uTagIndex;
1129 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001130 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001131 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001132 }
1133 }
1134 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001135 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001137
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001138 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001139 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001140 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001141 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001142 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001143 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001144 break;
1145 }
1146 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001147 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148 break;
1149 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001150 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1152 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001153 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1154 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001155 }
1156
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001157 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001158 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001159 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160
1161 } else {
1162 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001163 }
1164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001165
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001166Done:
1167 return nReturn;
1168}
1169
1170
1171/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001172 This layer takes care of map entries. It combines the label and data
1173 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001174 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001175static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001176GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001178 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001180 if(nReturn)
1181 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001182
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001183 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001184 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001185 goto Done;
1186 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001187
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001188 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1189 // In a map and caller wants maps decoded, not treated as arrays
1190
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001191 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001192 // If in a map and the right decoding mode, get the label
1193
Laurence Lundbladeee851742020-01-08 08:37:05 -08001194 // Save label in pDecodedItem and get the next which will
1195 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001196 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001197 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001198 if(nReturn)
1199 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301201 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001202
1203 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1204 // strings are always good labels
1205 pDecodedItem->label.string = LabelItem.val.string;
1206 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1207 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001208 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001209 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1210 goto Done;
1211 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1212 pDecodedItem->label.int64 = LabelItem.val.int64;
1213 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1214 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1215 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1216 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1217 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1218 pDecodedItem->label.string = LabelItem.val.string;
1219 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1220 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1221 } else {
1222 // label is not an int or a string. It is an arrray
1223 // or a float or such and this implementation doesn't handle that.
1224 // Also, tags on labels are ignored.
1225 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1226 goto Done;
1227 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001228 }
1229 } else {
1230 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001231 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1232 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1233 goto Done;
1234 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001235 // Decoding a map as an array
1236 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001237 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1238 // Cast is needed because of integer promotion
1239 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001240 }
1241 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001243Done:
1244 return nReturn;
1245}
1246
1247
Laurence Lundblade02625d42020-06-25 14:41:41 -07001248/*
1249 See if next item is a CBOR break. If it is, it is consumed,
1250 if not it is not consumed.
1251*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001252static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001253NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1254{
1255 *pbNextIsBreak = false;
1256 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001257 QCBORItem Peek;
1258 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1259 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1260 if(uReturn != QCBOR_SUCCESS) {
1261 return uReturn;
1262 }
1263 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001264 // It is not a break, rewind so it can be processed normally.
1265 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001266 } else {
1267 *pbNextIsBreak = true;
1268 }
1269 }
1270
1271 return QCBOR_SUCCESS;
1272}
1273
1274
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001275/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001276 An item was just consumed, now figure out if it was the
1277 end of an array or map that can be closed out. That
1278 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001279*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001280static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001281{
1282 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001283
Laurence Lundblade642282a2020-06-23 12:00:33 -07001284 /* This loops ascending nesting levels as long as there is ascending to do */
1285 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1286
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001287 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001288 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001289 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1290 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001291 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001292 break;
1293 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001294 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001295
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001296 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001297 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001298 bool bIsBreak = false;
1299 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1300 if(uReturn != QCBOR_SUCCESS) {
1301 goto Done;
1302 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001303
1304 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001305 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001306 break;
1307 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001308
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001309 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001310 /*
1311 Break occurred inside a bstr-wrapped CBOR or
1312 in the top level sequence. This is always an
1313 error because neither are an indefinte length
1314 map/array.
1315 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001316 uReturn = QCBOR_ERR_BAD_BREAK;
1317 goto Done;
1318 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001319 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001320 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001321
Laurence Lundblade02625d42020-06-25 14:41:41 -07001322 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001323
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001324 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001325 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001326 /* 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 -07001327 if(bMarkEnd) {
1328 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001329 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001330
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001331 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001332 break;
1333 }
1334
1335 /* Finally, actually ascend one level. */
1336 DecodeNesting_Ascend(&(pMe->nesting));
1337 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001338
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001339 uReturn = QCBOR_SUCCESS;
1340
1341Done:
1342 return uReturn;
1343}
1344
1345
1346/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001347 This the travesal going descending into and asecnding out of maps,
1348 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1349 indefinte length maps and arrays by looking at the item count or
1350 finding CBOR breaks. It detects the ends of the top-level sequence
1351 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001352 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001353static QCBORError
1354QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001355{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001356 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001357 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001358
Laurence Lundblade642282a2020-06-23 12:00:33 -07001359 /*
1360 If out of bytes to consume, it is either the end of the top-level
1361 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001362
Laurence Lundblade642282a2020-06-23 12:00:33 -07001363 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1364 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1365 CBOR is exited, the length is set back to the top-level's length
1366 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001367
Laurence Lundblade642282a2020-06-23 12:00:33 -07001368 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1369 when at the top level to allow other code below to process various
1370 errors when out of bytes to decode and not at the top level. Note
1371 that QCBORDecode_Finish() still needs to be called to be sure all
1372 nesting levels were closed out.
1373 */
1374 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1375 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001376 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001377 goto Done;
1378 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001379
Laurence Lundblade642282a2020-06-23 12:00:33 -07001380 /*
1381 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001382 array. The check for the end of an indefinite length array is
1383 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001384 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001385 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001386 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001387 goto Done;
1388 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001389
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001391 uReturn = GetNext_MapEntry(me, pDecodedItem);
1392 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001393 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001394 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301395
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 /*
1397 Breaks ending arrays/maps are always processed at the end of this
1398 function. They should never show up here.
1399 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301400 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001401 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301402 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301403 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001404
Laurence Lundblade642282a2020-06-23 12:00:33 -07001405 /*
1406 Record the nesting level for this data item before processing any
1407 of decrementing and descending.
1408 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001409 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001410
Laurence Lundblade642282a2020-06-23 12:00:33 -07001411
1412 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001413 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001414 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001415 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416
Laurence Lundblade02625d42020-06-25 14:41:41 -07001417 Empty maps and arrays descended into, but then ascended out
1418 of in the next chunk of code.
1419
1420 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421 encloses them so a decrement needs to be done for them too, but
1422 that is done only when all the items in them have been
1423 processed, not when they are opened with the exception of an
1424 empty map or array.
1425 */
1426 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1427 pDecodedItem->uDataType,
1428 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001429 if(uReturn != QCBOR_SUCCESS) {
1430 goto Done;
1431 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001432 }
1433
Laurence Lundblade02625d42020-06-25 14:41:41 -07001434 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1435 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1436 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437 /*
1438 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001439 - A non-aggregate like an integer or string
1440 - An empty definite length map or array
1441 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001442
1443 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001444 definite length map/array and break detection for an indefinite
1445 length map/array. If the end of the map/array was reached, then
1446 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001447 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001448 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001449 if(uReturn) {
1450 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001451 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301452 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001453
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001456 Tell the caller what level is next. This tells them what
1457 maps/arrays were closed out and makes it possible for them to
1458 reconstruct the tree with just the information returned in
1459 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001461 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001462 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001463 pDecodedItem->uNextNestLevel = 0;
1464 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001465 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001466 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001467
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001468Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001469 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001470 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001471 memset(pDecodedItem, 0, sizeof(QCBORItem));
1472 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001473 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001474}
1475
1476
Laurence Lundblade59289e52019-12-30 13:44:37 -08001477/*
1478 Mostly just assign the right data type for the date string.
1479 */
1480inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1481{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001482 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1483 return QCBOR_ERR_BAD_OPT_TAG;
1484 }
1485
1486 const UsefulBufC Temp = pDecodedItem->val.string;
1487 pDecodedItem->val.dateString = Temp;
1488 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1489 return QCBOR_SUCCESS;
1490}
1491
1492
1493/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001494 The epoch formatted date. Turns lots of different forms of encoding
1495 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001496 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001497static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001498{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001499 QCBORError nReturn = QCBOR_SUCCESS;
1500
1501 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1502
1503 switch (pDecodedItem->uDataType) {
1504
1505 case QCBOR_TYPE_INT64:
1506 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1507 break;
1508
1509 case QCBOR_TYPE_UINT64:
1510 if(pDecodedItem->val.uint64 > INT64_MAX) {
1511 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1512 goto Done;
1513 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001514 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001515 break;
1516
1517 case QCBOR_TYPE_DOUBLE:
1518 {
1519 // This comparison needs to be done as a float before
1520 // conversion to an int64_t to be able to detect doubles
1521 // that are too large to fit into an int64_t. A double
1522 // has 52 bits of preceision. An int64_t has 63. Casting
1523 // INT64_MAX to a double actually causes a round up which
1524 // is bad and wrong for the comparison because it will
1525 // allow conversion of doubles that can't fit into a
1526 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1527 // the cutoff point as if that rounds up in conversion to
1528 // double it will still be less than INT64_MAX. 0x7ff is
1529 // picked because it has 11 bits set.
1530 //
1531 // INT64_MAX seconds is on the order of 10 billion years,
1532 // and the earth is less than 5 billion years old, so for
1533 // most uses this conversion error won't occur even though
1534 // doubles can go much larger.
1535 //
1536 // Without the 0x7ff there is a ~30 minute range of time
1537 // values 10 billion years in the past and in the future
1538 // where this this code would go wrong.
1539 const double d = pDecodedItem->val.dfnum;
1540 if(d > (double)(INT64_MAX - 0x7ff)) {
1541 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1542 goto Done;
1543 }
1544 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1545 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1546 }
1547 break;
1548
1549 default:
1550 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1551 goto Done;
1552 }
1553 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1554
1555Done:
1556 return nReturn;
1557}
1558
1559
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001560/*
1561 Mostly just assign the right data type for the bignum.
1562 */
1563inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1564{
1565 // Stack Use: UsefulBuf 1 -- 16
1566 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1567 return QCBOR_ERR_BAD_OPT_TAG;
1568 }
1569 const UsefulBufC Temp = pDecodedItem->val.string;
1570 pDecodedItem->val.bigNum = Temp;
1571 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1572 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1573 : QCBOR_TYPE_NEGBIGNUM);
1574 return QCBOR_SUCCESS;
1575}
1576
1577
Laurence Lundblade59289e52019-12-30 13:44:37 -08001578#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1579/*
1580 Decode decimal fractions and big floats.
1581
1582 When called pDecodedItem must be the array that is tagged as a big
1583 float or decimal fraction, the array that has the two members, the
1584 exponent and mantissa.
1585
1586 This will fetch and decode the exponent and mantissa and put the
1587 result back into pDecodedItem.
1588 */
1589inline static QCBORError
1590QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1591{
1592 QCBORError nReturn;
1593
1594 // --- Make sure it is an array; track nesting level of members ---
1595 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1596 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1597 goto Done;
1598 }
1599
1600 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001601 // definite length arrays, but not for indefnite. Instead remember
1602 // the nesting level the two integers must be at, which is one
1603 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001604 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1605
1606 // --- Is it a decimal fraction or a bigfloat? ---
1607 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1608 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1609
1610 // --- Get the exponent ---
1611 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001612 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001613 if(nReturn != QCBOR_SUCCESS) {
1614 goto Done;
1615 }
1616 if(exponentItem.uNestingLevel != nNestLevel) {
1617 // Array is empty or a map/array encountered when expecting an int
1618 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1619 goto Done;
1620 }
1621 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1622 // Data arriving as an unsigned int < INT64_MAX has been converted
1623 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1624 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1625 // will be too large for this to handle and thus an error that will
1626 // get handled in the next else.
1627 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1628 } else {
1629 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1630 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1631 goto Done;
1632 }
1633
1634 // --- Get the mantissa ---
1635 QCBORItem mantissaItem;
1636 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1637 if(nReturn != QCBOR_SUCCESS) {
1638 goto Done;
1639 }
1640 if(mantissaItem.uNestingLevel != nNestLevel) {
1641 // Mantissa missing or map/array encountered when expecting number
1642 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1643 goto Done;
1644 }
1645 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1646 // Data arriving as an unsigned int < INT64_MAX has been converted
1647 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1648 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1649 // will be too large for this to handle and thus an error that
1650 // will get handled in an else below.
1651 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1652 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1653 // Got a good big num mantissa
1654 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1655 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001656 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1657 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1658 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001659 } else {
1660 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1661 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1662 goto Done;
1663 }
1664
1665 // --- Check that array only has the two numbers ---
1666 if(mantissaItem.uNextNestLevel == nNestLevel) {
1667 // Extra items in the decimal fraction / big num
1668 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1669 goto Done;
1670 }
1671
1672Done:
1673
1674 return nReturn;
1675}
1676#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1677
1678
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001679
1680/*
1681 */
1682inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1683{
1684 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1685 return QCBOR_ERR_BAD_OPT_TAG;
1686 }
1687 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1688 return QCBOR_SUCCESS;
1689}
1690
1691
1692inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1693{
1694 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1695 return QCBOR_ERR_BAD_OPT_TAG;
1696 }
1697 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1698 return QCBOR_SUCCESS;
1699}
1700
1701
1702inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1703{
1704 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1705 return QCBOR_ERR_BAD_OPT_TAG;
1706 }
1707 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1708 return QCBOR_SUCCESS;
1709}
1710
1711
1712inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1713{
1714 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1715 return QCBOR_ERR_BAD_OPT_TAG;
1716 }
1717 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1718 return QCBOR_SUCCESS;
1719}
1720
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001721inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1722{
1723 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1724 return QCBOR_ERR_BAD_OPT_TAG;
1725 }
1726 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1727 return QCBOR_SUCCESS;
1728}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001729
1730inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1731{
1732 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1733 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1734 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1735 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1736 } else {
1737 return QCBOR_ERR_BAD_OPT_TAG;
1738 }
1739 return QCBOR_SUCCESS;
1740}
1741
1742
1743/*
1744 */
1745inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1746{
1747 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1748 return QCBOR_ERR_BAD_OPT_TAG;
1749 }
1750 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1751 return QCBOR_SUCCESS;
1752}
1753
1754
Laurence Lundblade59289e52019-12-30 13:44:37 -08001755/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001756 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001757 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001758QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001759QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001760{
1761 QCBORError nReturn;
1762
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001763 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 if(nReturn != QCBOR_SUCCESS) {
1765 goto Done;
1766 }
1767
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001768 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1769 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001770
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001771 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 nReturn = DecodeDateString(pDecodedItem);
1773 break;
1774
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001775 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001776 nReturn = DecodeDateEpoch(pDecodedItem);
1777 break;
1778
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001779 case CBOR_TAG_POS_BIGNUM:
1780 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001781 nReturn = DecodeBigNum(pDecodedItem);
1782 break;
1783
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001784 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1785 case CBOR_TAG_DECIMAL_FRACTION:
1786 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001787 // For aggregate tagged types, what goes into pTags is only collected
1788 // from the surrounding data item, not the contents, so pTags is not
1789 // passed on here.
1790
1791 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1792 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001793 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001794
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001795 case CBOR_TAG_CBOR:
1796 nReturn = DecodeWrappedCBOR(pDecodedItem);
1797 break;
1798
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001799 case CBOR_TAG_URI:
1800 nReturn = DecodeURI(pDecodedItem);
1801 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001802
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001803 case CBOR_TAG_B64URL:
1804 nReturn = DecodeB64URL(pDecodedItem);
1805 break;
1806
1807 case CBOR_TAG_B64:
1808 nReturn = DecodeB64(pDecodedItem);
1809 break;
1810
1811 case CBOR_TAG_MIME:
1812 case CBOR_TAG_BINARY_MIME:
1813 nReturn = DecodeMIME(pDecodedItem);
1814 break;
1815
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001816 case CBOR_TAG_REGEX:
1817 nReturn = DecodeRegex(pDecodedItem);
1818 break;
1819
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001820 case CBOR_TAG_BIN_UUID:
1821 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001822 break;
1823
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001824 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001825 // The end of the tag list or no tags
1826 // Successful exit from the loop.
1827 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001828
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001829 default:
1830 // A tag that is not understood
1831 // A successful exit from the loop
1832 goto Done;
1833
1834 }
1835 if(nReturn != QCBOR_SUCCESS) {
1836 goto Done;
1837 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001838 }
1839
1840Done:
1841 if(nReturn != QCBOR_SUCCESS) {
1842 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1843 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1844 }
1845 return nReturn;
1846}
1847
1848
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001849QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1850{
1851 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1852
1853 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1854
1855 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1856
1857 return uErr;
1858}
1859
1860
Laurence Lundblade59289e52019-12-30 13:44:37 -08001861/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001862 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001863 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001864QCBORError
1865QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1866 QCBORItem *pDecodedItem,
1867 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001868{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001869 QCBORError nReturn;
1870
1871 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1872 if(nReturn != QCBOR_SUCCESS) {
1873 return nReturn;
1874 }
1875
1876 if(pTags != NULL) {
1877 pTags->uNumUsed = 0;
1878 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001879 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001880 break;
1881 }
1882 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1883 return QCBOR_ERR_TOO_MANY_TAGS;
1884 }
1885 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1886 pTags->uNumUsed++;
1887 }
1888 }
1889
1890 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001891}
1892
1893
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001894/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301895 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301896 next one down. If a layer has no work to do for a particular item
1897 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001898
Laurence Lundblade59289e52019-12-30 13:44:37 -08001899 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1900 tagged data items, turning them into the local C representation.
1901 For the most simple it is just associating a QCBOR_TYPE with the data. For
1902 the complex ones that an aggregate of data items, there is some further
1903 decoding and a little bit of recursion.
1904
1905 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301906 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301907 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001908 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001909
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301910 - GetNext_MapEntry -- This handles the combining of two
1911 items, the label and the data, that make up a map entry.
1912 It only does work on maps. It combines the label and data
1913 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001914
Laurence Lundblade59289e52019-12-30 13:44:37 -08001915 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1916 tags into bit flags associated with the data item. No actual decoding
1917 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001918
Laurence Lundblade59289e52019-12-30 13:44:37 -08001919 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301920 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301921 string allocater to create contiguous space for the item. It
1922 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001923
Laurence Lundblade59289e52019-12-30 13:44:37 -08001924 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1925 atomic data item has a "major type", an integer "argument" and optionally
1926 some content. For text and byte strings, the content is the bytes
1927 that make up the string. These are the smallest data items that are
1928 considered to be well-formed. The content may also be other data items in
1929 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001930
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001931 Roughly this takes 300 bytes of stack for vars. Need to
1932 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001933
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301934 */
1935
1936
1937/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001938 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001939 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001940int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001941 const QCBORItem *pItem,
1942 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001943{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001944 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001945 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001946 break;
1947 }
1948 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1949 return 1;
1950 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001952
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001953 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001954}
1955
1956
1957/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001958 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001959 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001960QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001961{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001962 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001963
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001964 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001965 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001966 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1967 goto Done;
1968 }
1969
1970 // Error out if not all the bytes are consumed
1971 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1972 nReturn = QCBOR_ERR_EXTRA_BYTES;
1973 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001974
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001975Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301976 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001977 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001978 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001979
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001980 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001981}
1982
1983
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001984/*
1985Public function, see header qcbor/qcbor_decode.h file
1986*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001987uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1988 const QCBORItem *pItem,
1989 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001990{
1991 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
1992 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001993 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001994 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001995 }
1996}
1997
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001998
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001999/*
2000
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002001Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002002
Laurence Lundbladeee851742020-01-08 08:37:05 -08002003 - Hit end of input before it was expected while decoding type and
2004 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002005
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002006 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002007
Laurence Lundbladeee851742020-01-08 08:37:05 -08002008 - Hit end of input while decoding a text or byte string
2009 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002010
Laurence Lundbladeee851742020-01-08 08:37:05 -08002011 - Encountered conflicting tags -- e.g., an item is tagged both a date
2012 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002013
Laurence Lundbladeee851742020-01-08 08:37:05 -08002014 - Encontered an array or mapp that has too many items
2015 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002016
Laurence Lundbladeee851742020-01-08 08:37:05 -08002017 - Encountered array/map nesting that is too deep
2018 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002019
Laurence Lundbladeee851742020-01-08 08:37:05 -08002020 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2021 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002022
Laurence Lundbladeee851742020-01-08 08:37:05 -08002023 - The type of a map label is not a string or int
2024 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002025
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002026 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002027
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002028 */
2029
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002030
2031
Laurence Lundbladef6531662018-12-04 10:42:22 +09002032
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002033/* ===========================================================================
2034 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002036 This implements a simple sting allocator for indefinite length
2037 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2038 implements the function type QCBORStringAllocate and allows easy
2039 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002040
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002041 This particular allocator is built-in for convenience. The caller
2042 can implement their own. All of this following code will get
2043 dead-stripped if QCBORDecode_SetMemPool() is not called.
2044
2045 This is a very primitive memory allocator. It does not track
2046 individual allocations, only a high-water mark. A free or
2047 reallocation must be of the last chunk allocated.
2048
2049 The size of the pool and offset to free memory are packed into the
2050 first 8 bytes of the memory pool so we don't have to keep them in
2051 the decode context. Since the address of the pool may not be
2052 aligned, they have to be packed and unpacked as if they were
2053 serialized data of the wire or such.
2054
2055 The sizes packed in are uint32_t to be the same on all CPU types
2056 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002057 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002058
2059
Laurence Lundbladeee851742020-01-08 08:37:05 -08002060static inline int
2061MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002062{
2063 // Use of UsefulInputBuf is overkill, but it is convenient.
2064 UsefulInputBuf UIB;
2065
Laurence Lundbladeee851742020-01-08 08:37:05 -08002066 // Just assume the size here. It was checked during SetUp so
2067 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002068 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2069 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2070 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2071 return UsefulInputBuf_GetError(&UIB);
2072}
2073
2074
Laurence Lundbladeee851742020-01-08 08:37:05 -08002075static inline int
2076MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002077{
2078 // Use of UsefulOutBuf is overkill, but convenient. The
2079 // length check performed here is useful.
2080 UsefulOutBuf UOB;
2081
2082 UsefulOutBuf_Init(&UOB, Pool);
2083 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2084 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2085 return UsefulOutBuf_GetError(&UOB);
2086}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002087
2088
2089/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002090 Internal function for an allocation, reallocation free and destuct.
2091
2092 Having only one function rather than one each per mode saves space in
2093 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002094
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002095 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2096 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002097static UsefulBuf
2098MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002099{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002100 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002101
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002102 uint32_t uPoolSize;
2103 uint32_t uFreeOffset;
2104
2105 if(uNewSize > UINT32_MAX) {
2106 // This allocator is only good up to 4GB. This check should
2107 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2108 goto Done;
2109 }
2110 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2111
2112 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2113 goto Done;
2114 }
2115
2116 if(uNewSize) {
2117 if(pMem) {
2118 // REALLOCATION MODE
2119 // Calculate pointer to the end of the memory pool. It is
2120 // assumed that pPool + uPoolSize won't wrap around by
2121 // assuming the caller won't pass a pool buffer in that is
2122 // not in legitimate memory space.
2123 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2124
2125 // Check that the pointer for reallocation is in the range of the
2126 // pool. This also makes sure that pointer math further down
2127 // doesn't wrap under or over.
2128 if(pMem >= pPool && pMem < pPoolEnd) {
2129 // Offset to start of chunk for reallocation. This won't
2130 // wrap under because of check that pMem >= pPool. Cast
2131 // is safe because the pool is always less than UINT32_MAX
2132 // because of check in QCBORDecode_SetMemPool().
2133 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2134
2135 // Check to see if the allocation will fit. uPoolSize -
2136 // uMemOffset will not wrap under because of check that
2137 // pMem is in the range of the uPoolSize by check above.
2138 if(uNewSize <= uPoolSize - uMemOffset) {
2139 ReturnValue.ptr = pMem;
2140 ReturnValue.len = uNewSize;
2141
2142 // Addition won't wrap around over because uNewSize was
2143 // checked to be sure it is less than the pool size.
2144 uFreeOffset = uMemOffset + uNewSize32;
2145 }
2146 }
2147 } else {
2148 // ALLOCATION MODE
2149 // uPoolSize - uFreeOffset will not underflow because this
2150 // pool implementation makes sure uFreeOffset is always
2151 // smaller than uPoolSize through this check here and
2152 // reallocation case.
2153 if(uNewSize <= uPoolSize - uFreeOffset) {
2154 ReturnValue.len = uNewSize;
2155 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002156 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002157 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002158 }
2159 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002160 if(pMem) {
2161 // FREE MODE
2162 // Cast is safe because of limit on pool size in
2163 // QCBORDecode_SetMemPool()
2164 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2165 } else {
2166 // DESTRUCT MODE
2167 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002168 }
2169 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002170
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002171 UsefulBuf Pool = {pPool, uPoolSize};
2172 MemPool_Pack(Pool, uFreeOffset);
2173
2174Done:
2175 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002176}
2177
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002178
Laurence Lundbladef6531662018-12-04 10:42:22 +09002179/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002180 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002181 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002182QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2183 UsefulBuf Pool,
2184 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002185{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002186 // The pool size and free mem offset are packed into the beginning
2187 // of the pool memory. This compile time check make sure the
2188 // constant in the header is correct. This check should optimize
2189 // down to nothing.
2190 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002191 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002194 // The pool size and free offset packed in to the beginning of pool
2195 // memory are only 32-bits. This check will optimize out on 32-bit
2196 // machines.
2197 if(Pool.len > UINT32_MAX) {
2198 return QCBOR_ERR_BUFFER_TOO_LARGE;
2199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002200
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002201 // This checks that the pool buffer given is big enough.
2202 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2203 return QCBOR_ERR_BUFFER_TOO_SMALL;
2204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002205
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002206 pMe->StringAllocator.pfAllocator = MemPool_Function;
2207 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2208 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002209
Laurence Lundblade30816f22018-11-10 13:40:22 +07002210 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002211}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002212
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002213
2214
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002215
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002216
2217
2218/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002219 Consume an entire map or array (and do next to
2220 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002221 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002222static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002223ConsumeItem(QCBORDecodeContext *pMe,
2224 const QCBORItem *pItemToConsume,
2225 uint_fast8_t *puNextNestLevel)
2226{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002227 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002228 QCBORItem Item;
2229
Laurence Lundblade02625d42020-06-25 14:41:41 -07002230 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002231
Laurence Lundblade02625d42020-06-25 14:41:41 -07002232 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002233 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002234
Laurence Lundblade1341c592020-04-11 14:19:05 -07002235 /* This works for definite and indefinite length
2236 * maps and arrays by using the nesting level
2237 */
2238 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002239 uReturn = QCBORDecode_GetNext(pMe, &Item);
2240 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002241 goto Done;
2242 }
2243 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002244
Laurence Lundblade1341c592020-04-11 14:19:05 -07002245 if(puNextNestLevel != NULL) {
2246 *puNextNestLevel = Item.uNextNestLevel;
2247 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002248 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002249
Laurence Lundblade1341c592020-04-11 14:19:05 -07002250 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002251 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002252 if(puNextNestLevel != NULL) {
2253 /* Just pass the nesting level through */
2254 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2255 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002256 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002257 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002258
2259Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002260 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002261}
2262
2263
Laurence Lundblade1341c592020-04-11 14:19:05 -07002264/* Return true if the labels in Item1 and Item2 are the same.
2265 Works only for integer and string labels. Returns false
2266 for any other type. */
2267static inline bool
2268MatchLabel(QCBORItem Item1, QCBORItem Item2)
2269{
2270 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2271 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2272 return true;
2273 }
2274 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002275 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 return true;
2277 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002278 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002279 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2280 return true;
2281 }
2282 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2283 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2284 return true;
2285 }
2286 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002287
Laurence Lundblade1341c592020-04-11 14:19:05 -07002288 /* Other label types are never matched */
2289 return false;
2290}
2291
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002292
2293/*
2294 Returns true if Item1 and Item2 are the same type
2295 or if either are of QCBOR_TYPE_ANY.
2296 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002297static inline bool
2298MatchType(QCBORItem Item1, QCBORItem Item2)
2299{
2300 if(Item1.uDataType == Item2.uDataType) {
2301 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002302 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002303 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002304 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002305 return true;
2306 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002307 return false;
2308}
2309
2310
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002311/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002312 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002313
2314 @param[in] pMe The decode context to search.
2315 @param[in,out] pItemArray The items to search for and the items found.
2316 @param[in] pCBContext Context for the not-found item call back
2317 @param[in] pfCallback Function to call on items not matched in pItemArray
2318
2319 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2320
2321 @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.
2322
2323 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2324
2325 @retval Also errors returned by QCBORDecode_GetNext().
2326
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002327 On input pItemArray contains a list of labels and data types
2328 of items to be found.
2329
2330 On output the fully retrieved items are filled in with
2331 values and such. The label was matched, so it never changes.
2332
2333 If an item was not found, its data type is set to none.
2334
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002335 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002336static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002337MapSearch(QCBORDecodeContext *pMe,
2338 QCBORItem *pItemArray,
2339 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002340 void *pCBContext,
2341 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002342{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002343 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002344
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002345 QCBORDecodeNesting SaveNesting;
2346 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002347
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002348 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002349 UsefulInputBuf_Seek(&(pMe->InBuf),
2350 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002351
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002352 /*
2353 Loop over all the items in the map. They could be
2354 deeply nested and this should handle both definite
2355 and indefinite length maps and arrays, so this
2356 adds some complexity.
2357 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002358 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002359
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002360 uint_fast8_t uNextNestLevel;
2361
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002362 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002363
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002364 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002365 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002366 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002367 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002368
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002369 /* Get the item */
2370 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002371 uReturn = QCBORDecode_GetNext(pMe, &Item);
2372 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002373 /* Got non-well-formed CBOR */
2374 goto Done;
2375 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002376
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002377 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002378 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002379 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002380 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002381 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002382 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002383 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2384 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002385 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002386 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002387 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002388 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002389 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002390 goto Done;
2391 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002392
2393 /* Successful match. Return the item. */
2394 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002395 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002396 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002397 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002398 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002399 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002400 /*
2401 Call the callback on unmatched labels.
2402 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002403 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002404 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002405 */
2406 if(pfCallback) {
2407 uReturn = (*pfCallback)(pCBContext, &Item);
2408 if(uReturn != QCBOR_SUCCESS) {
2409 goto Done;
2410 }
2411 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002412 }
2413 }
2414
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002415 /*
2416 Consume the item whether matched or not. This
2417 does the work of traversing maps and array and
2418 everything in them. In this loop only the
2419 items at the current nesting level are examined
2420 to match the labels.
2421 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002422 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2423 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002424 goto Done;
2425 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002426
2427 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002428
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002429 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002430
2431 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002432 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2433 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002434
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002435 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002436 int i;
2437 QCBORItem *pIterator;
2438 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002439 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002440 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002441 }
2442 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002443
2444Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002445 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002446
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002447 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002448}
2449
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002450
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002451/*
2452Public function, see header qcbor/qcbor_decode.h file
2453*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002454void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2455 int64_t nLabel,
2456 uint8_t uQcborType,
2457 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002458{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002459 if(pMe->uLastError != QCBOR_SUCCESS) {
2460 return;
2461 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002463 QCBORItem OneItemSeach[2];
2464 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2465 OneItemSeach[0].label.int64 = nLabel;
2466 OneItemSeach[0].uDataType = uQcborType;
2467 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002468
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002469 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002470 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002471 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002472 }
2473
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002474 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2475 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 }
2477
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002478 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002479}
2480
2481
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002482/*
2483Public function, see header qcbor/qcbor_decode.h file
2484*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002485void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2486 const char *szLabel,
2487 uint8_t uQcborType,
2488 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002489{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002490 if(pMe->uLastError != QCBOR_SUCCESS) {
2491 return;
2492 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002493
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002494 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002495 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2496 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2497 OneItemSeach[0].uDataType = uQcborType;
2498 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002499
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002500 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002501 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002502 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002503 }
2504
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002505 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002506 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 }
2508
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002509 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002510}
2511
2512
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002513/**
2514 @param[in] TagSpec Specification for matching tags.
2515 @param[in] uDataType A QCBOR data type
2516
2517 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2518 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2519
2520 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2521 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002522static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002523{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002524 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2525 /* Must match the tag */
2526 if(uDataType == TagSpec.uTaggedType) {
2527 return QCBOR_SUCCESS;
2528 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002529 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002530 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2531 /* Must check all the possible types for the tag content */
2532 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002533 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2534 return QCBOR_SUCCESS;
2535 }
2536 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002537 /* Didn't match any of the tag content types */
2538 /* Check the tag for the either case */
2539 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2540 if(uDataType == TagSpec.uTaggedType) {
2541 return QCBOR_SUCCESS;
2542 }
2543 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002544 }
2545
2546 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002547}
2548
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002549
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002550// Semi-private
2551// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002552void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2553 int64_t nLabel,
2554 TagSpecification TagSpec,
2555 QCBORItem *pItem)
2556{
2557 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2558 if(pMe->uLastError != QCBOR_SUCCESS) {
2559 return;
2560 }
2561
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002562 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002563}
2564
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002565// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002566void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2567 const char *szLabel,
2568 TagSpecification TagSpec,
2569 QCBORItem *pItem)
2570{
2571 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2572 if(pMe->uLastError != QCBOR_SUCCESS) {
2573 return;
2574 }
2575
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002576 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002577}
2578
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002579// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002580void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2581 int64_t nLabel,
2582 TagSpecification TagSpec,
2583 UsefulBufC *pString)
2584{
2585 QCBORItem Item;
2586 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2587 if(pMe->uLastError == QCBOR_SUCCESS) {
2588 *pString = Item.val.string;
2589 }
2590}
2591
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002592// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002593void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2594 const char * szLabel,
2595 TagSpecification TagSpec,
2596 UsefulBufC *pString)
2597{
2598 QCBORItem Item;
2599 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2600 if(pMe->uLastError == QCBOR_SUCCESS) {
2601 *pString = Item.val.string;
2602 }
2603}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002604
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002605/*
2606Public function, see header qcbor/qcbor_decode.h file
2607*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002608QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2609{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002610 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002611}
2612
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002613/*
2614Public function, see header qcbor/qcbor_decode.h file
2615*/
2616QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2617 QCBORItem *pItemList,
2618 void *pCallbackCtx,
2619 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002620{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002621 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002622}
2623
2624
Laurence Lundblade34691b92020-05-18 22:25:25 -07002625static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002626{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002627 if(pMe->uLastError != QCBOR_SUCCESS) {
2628 // Already in error state; do nothing.
2629 return;
2630 }
2631
2632 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002633 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002634 if(pMe->uLastError != QCBOR_SUCCESS) {
2635 return;
2636 }
2637
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002638 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002639 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002640
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002641 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002642 be at the right place.
2643
2644 The UsefulInBuf offset could be anywhere, so no assumption is
2645 made about it.
2646
2647 No assumption is made about the pre-order nesting level either.
2648
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002649 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002650 the map level that is being entered.
2651 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002652 /* Seek to the data item that is the map or array */
2653 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002654
2655 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002656
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002657 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002658}
2659
2660
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002661/*
2662Public function, see header qcbor/qcbor_decode.h file
2663*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002664void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002665{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002666 QCBORItem OneItemSeach[2];
2667 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2668 OneItemSeach[0].label.int64 = nLabel;
2669 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2670 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002671
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002672 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002673 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002674}
2675
2676
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002677/*
2678Public function, see header qcbor/qcbor_decode.h file
2679*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002680void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002681{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002682 QCBORItem OneItemSeach[2];
2683 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2684 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2685 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2686 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002687
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002688 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002689}
2690
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002691/*
2692Public function, see header qcbor/qcbor_decode.h file
2693*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002694void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002695{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002696 QCBORItem OneItemSeach[2];
2697 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2698 OneItemSeach[0].label.int64 = nLabel;
2699 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2700 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002701
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002702 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002703}
2704
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002705/*
2706Public function, see header qcbor/qcbor_decode.h file
2707*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002708void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2709{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002710 QCBORItem OneItemSeach[2];
2711 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2712 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2713 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2714 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002716 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717}
2718
2719
Laurence Lundblade02625d42020-06-25 14:41:41 -07002720// Semi-private function
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002721void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002722{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002723 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002724 if(pMe->uLastError != QCBOR_SUCCESS) {
2725 // Already in error state; do nothing.
2726 return;
2727 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002728
2729 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002730 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002731 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002732 if(pMe->uLastError != QCBOR_SUCCESS) {
2733 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002734 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002735 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002736 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2737 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002738 }
2739
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002740 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002742 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002743 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002744
Laurence Lundblade02625d42020-06-25 14:41:41 -07002745 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002746}
2747
Laurence Lundblade02625d42020-06-25 14:41:41 -07002748
2749/*
2750 This is for exiting a level that is a bounded map, array or bstr
2751 wrapped CBOR. It is the work common to these.
2752
2753 One chunk of work is to set up the pre-order traversal so it is at
2754 the item just after the bounded map, array or bstr that is being
2755 exited. This is somewhat complex.
2756
2757 The other work is to level-up the bounded mode to next higest bounded
2758 mode or the top level if there isn't one.
2759 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002760static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002761ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002762{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002763 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002764
Laurence Lundblade02625d42020-06-25 14:41:41 -07002765 /*
2766 First the pre-order-traversal byte offset is positioned to the
2767 item just after the bounded mode item that was just consumed.
2768 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002769 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2770
Laurence Lundblade02625d42020-06-25 14:41:41 -07002771 /*
2772 Next, set the current nesting level to one above the bounded level
2773 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002774
Laurence Lundblade02625d42020-06-25 14:41:41 -07002775 DecodeNesting_CheckBoundedType() is always called before this and
2776 makes sure pCurrentBounded is valid.
2777 */
2778 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2779
2780 /*
2781 This does the complex work of leveling up the pre-order traversal
2782 when the end of a map or array or another bounded level is
2783 reached. It may do nothing, or ascend all the way to the top
2784 level.
2785 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002786 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002787 if(uErr != QCBOR_SUCCESS) {
2788 goto Done;
2789 }
2790
Laurence Lundblade02625d42020-06-25 14:41:41 -07002791 /*
2792 This makes the next highest bounded level the current bounded
2793 level. If there is no next highest level, then no bounded mode is
2794 in effect.
2795 */
2796 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002797
Laurence Lundblade02625d42020-06-25 14:41:41 -07002798 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002799
2800Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002801 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002802 return uErr;
2803}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002804
Laurence Lundblade02625d42020-06-25 14:41:41 -07002805
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002806// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002807void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002808{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002809 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002810 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002811 return;
2812 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002813
Laurence Lundblade02625d42020-06-25 14:41:41 -07002814 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002815
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002817 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2818 goto Done;
2819 }
2820
Laurence Lundblade02625d42020-06-25 14:41:41 -07002821 /*
2822 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002823 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002824 from previous map search, then do a dummy search.
2825 */
2826 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002827 QCBORItem Dummy;
2828 Dummy.uLabelType = QCBOR_TYPE_NONE;
2829 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2830 if(uErr != QCBOR_SUCCESS) {
2831 goto Done;
2832 }
2833 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002834
Laurence Lundblade02625d42020-06-25 14:41:41 -07002835 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002836
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002837Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002838 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002839}
2840
2841
Laurence Lundblade1341c592020-04-11 14:19:05 -07002842void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002844 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002845 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2846 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002847}
2848
2849
Laurence Lundblade1341c592020-04-11 14:19:05 -07002850
Laurence Lundblade02625d42020-06-25 14:41:41 -07002851static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe,
2852 const QCBORItem *pItem,
2853 uint8_t uTagRequirement,
2854 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002855{
2856 if(pMe->uLastError != QCBOR_SUCCESS) {
2857 // Already in error state; do nothing.
2858 return pMe->uLastError;
2859 }
2860
2861 QCBORError uError = QCBOR_SUCCESS;
2862
2863 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2864 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2865 goto Done;;
2866 }
2867
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002868 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002869 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2870
2871 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2872 if(uError != QCBOR_SUCCESS) {
2873 goto Done;
2874 }
2875
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002876 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002877 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002878 so the increment in NestLevelAscender called by ExitBoundedLevel()
2879 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002880 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002881 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002882
2883 if(pBstr) {
2884 *pBstr = pItem->val.string;
2885 }
2886
2887 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002888
2889 // Need to move UIB input cursor to the right place
2890
2891 // Really this is a subtraction and an assignment; not much code
2892 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002893 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002894
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002895 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002896
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002897 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2898
2899 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002900
Laurence Lundblade02625d42020-06-25 14:41:41 -07002901 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2902 uPreviousLength,
2903 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002904Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002905 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002906
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002907 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002908}
2909
2910
Laurence Lundblade02625d42020-06-25 14:41:41 -07002911/*
2912 Public function, see header qcbor/qcbor_decode.h file
2913 */
2914void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
2915 uint8_t uTagRequirement,
2916 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002917{
2918 if(pMe->uLastError != QCBOR_SUCCESS) {
2919 // Already in error state; do nothing.
2920 return;
2921 }
2922
2923 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002924 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002925 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2926 if(pMe->uLastError != QCBOR_SUCCESS) {
2927 return;
2928 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002929
Laurence Lundblade02625d42020-06-25 14:41:41 -07002930 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe,
2931 &Item,
2932 uTagRequirement,
2933 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002934}
2935
2936
Laurence Lundblade02625d42020-06-25 14:41:41 -07002937/*
2938 Public function, see header qcbor/qcbor_decode.h file
2939 */
2940void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2941 uint8_t uTagRequirement,
2942 int64_t nLabel,
2943 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002944{
2945 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002946 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002947
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002948 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002949}
2950
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002951
Laurence Lundblade02625d42020-06-25 14:41:41 -07002952/*
2953 Public function, see header qcbor/qcbor_decode.h file
2954 */
2955void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
2956 uint8_t uTagRequirement,
2957 const char *szLabel,
2958 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002959{
2960 QCBORItem Item;
2961 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2962
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002963 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002964}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002965
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002966
Laurence Lundblade02625d42020-06-25 14:41:41 -07002967/*
2968 Public function, see header qcbor/qcbor_decode.h file
2969 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002970void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002971{
Laurence Lundblade02625d42020-06-25 14:41:41 -07002972 if(pMe->uLastError != QCBOR_SUCCESS) {
2973 // Already in error state; do nothing.
2974 return;
2975 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002976
Laurence Lundblade02625d42020-06-25 14:41:41 -07002977 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2978 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
2979 return;
2980 }
2981
2982 /*
2983 Reset the length of the UsefulInputBuf to what it was before
2984 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002985 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002986 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
2987 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002988
2989
Laurence Lundblade02625d42020-06-25 14:41:41 -07002990 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002991 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002992}
2993
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002994
Laurence Lundbladee6430642020-03-14 21:15:44 -07002995
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002996
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002997
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002998
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002999
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003000
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003001static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3002{
3003 switch(pItem->uDataType) {
3004 case QCBOR_TYPE_TRUE:
3005 *pBool = true;
3006 return QCBOR_SUCCESS;
3007 break;
3008
3009 case QCBOR_TYPE_FALSE:
3010 *pBool = false;
3011 return QCBOR_SUCCESS;
3012 break;
3013
3014 default:
3015 return QCBOR_ERR_UNEXPECTED_TYPE;
3016 break;
3017 }
3018}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003019
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003020/*
3021Public function, see header qcbor/qcbor_decode.h file
3022*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003023void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003024{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003025 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003026 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003027 return;
3028 }
3029
Laurence Lundbladec4537442020-04-14 18:53:22 -07003030 QCBORError nError;
3031 QCBORItem Item;
3032
3033 nError = QCBORDecode_GetNext(pMe, &Item);
3034 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003035 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003036 return;
3037 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003038 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003039}
3040
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003041/*
3042Public function, see header qcbor/qcbor_decode.h file
3043*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003044void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003045{
3046 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003047 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003048
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003049 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003050}
3051
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003052/*
3053Public function, see header qcbor/qcbor_decode.h file
3054*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003055void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3056{
3057 QCBORItem Item;
3058 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3059
3060 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3061}
3062
3063
3064
3065void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003066{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003067 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003068 // Already in error state, do nothing
3069 return;
3070 }
3071
3072 QCBORError nError;
3073 QCBORItem Item;
3074
3075 nError = QCBORDecode_GetNext(pMe, &Item);
3076 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003077 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003078 return;
3079 }
3080
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003081 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3082
3083 if(pMe->uLastError == QCBOR_SUCCESS) {
3084 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003085 }
3086}
3087
Laurence Lundbladec4537442020-04-14 18:53:22 -07003088
3089
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003090
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003091static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003092{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003093 *pbIsNegative = false;
3094
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003095 bool bMustBeTagged = true; // TODO: fix this --- they have to tell us if they are expecting positive or negative
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003096
3097 switch(pItem->uDataType) {
3098 case QCBOR_TYPE_BYTE_STRING:
3099 // TODO: check that there is no tag here?
3100 if(bMustBeTagged) {
3101 return QCBOR_ERR_UNEXPECTED_TYPE;
3102 } else {
3103 *pValue = pItem->val.string;
3104 return QCBOR_SUCCESS;
3105 }
3106 break;
3107
3108 case QCBOR_TYPE_POSBIGNUM:
3109 *pValue = pItem->val.string;
3110 return QCBOR_SUCCESS;
3111 break;
3112
3113 case QCBOR_TYPE_NEGBIGNUM:
3114 *pbIsNegative = true;
3115 *pValue = pItem->val.string;
3116 return QCBOR_SUCCESS;
3117 break;
3118
3119 default:
3120 return QCBOR_ERR_UNEXPECTED_TYPE;
3121 break;
3122 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003123}
3124
3125
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003126/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003127 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3128 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3129 will always be false on the asumption that it is positive, but it can be interpretted as
3130 negative if the the sign is know from other context.
3131 @param[out] pValue The bytes that make up the big num
3132 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3133
3134 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3135 a positive big num or a negative big num.
3136
3137 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003138void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003139{
3140 if(pMe->uLastError != QCBOR_SUCCESS) {
3141 // Already in error state, do nothing
3142 return;
3143 }
3144
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003145 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003146 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3147 if(uError != QCBOR_SUCCESS) {
3148 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003149 return;
3150 }
3151
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003152 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003153}
3154
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003155/*
3156Public function, see header qcbor/qcbor_decode.h file
3157*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003158void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003159{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003160 QCBORItem Item;
3161 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003162
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003163 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003164}
3165
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003166/*
3167Public function, see header qcbor/qcbor_decode.h file
3168*/
3169void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3170{
3171 QCBORItem Item;
3172 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3173
3174 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3175}
3176
3177
3178
3179// Semi private
3180QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3181{
3182 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3183 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3184
3185 QCBORError uReturn;
3186
3187 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3188 *pMessage = pItem->val.string;
3189 if(pbIsNot7Bit != NULL) {
3190 *pbIsNot7Bit = false;
3191 }
3192 uReturn = QCBOR_SUCCESS;
3193 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3194 *pMessage = pItem->val.string;
3195 if(pbIsNot7Bit != NULL) {
3196 *pbIsNot7Bit = true;
3197 }
3198 uReturn = QCBOR_SUCCESS;
3199
3200 } else {
3201 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3202 }
3203
3204 return uReturn;
3205}
3206
3207
3208
3209
3210
Laurence Lundbladec4537442020-04-14 18:53:22 -07003211
3212
3213
Laurence Lundbladee6430642020-03-14 21:15:44 -07003214
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003215typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003216
3217
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003218// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003219static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003220{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003221 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003222
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003223 if(uResult != 0) {
3224 /* This loop will run a maximum of 19 times because
3225 * UINT64_MAX < 10 ^^ 19. More than that will cause
3226 * exit with the overflow error
3227 */
3228 for(; nExponent > 0; nExponent--) {
3229 if(uResult > UINT64_MAX / 10) {
3230 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3231 }
3232 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003233 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003234
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003235 for(; nExponent < 0; nExponent++) {
3236 uResult = uResult / 10;
3237 if(uResult == 0) {
3238 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3239 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003240 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003241 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003242 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003243
3244 *puResult = uResult;
3245
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003246 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003247}
3248
3249
Laurence Lundbladee6430642020-03-14 21:15:44 -07003250/* Convert a decimal fraction to an int64_t without using
3251 floating point or math libraries. Most decimal fractions
3252 will not fit in an int64_t and this will error out with
3253 under or overflow
3254 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003255static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003256{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003257 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003258
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003259 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003260
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003261 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003262 * INT64_MAX < 2^31. More than that will cause
3263 * exist with the overflow error
3264 */
3265 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003266 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003267 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003268 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003269 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003270 nExponent--;
3271 }
3272
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003273 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003274 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003275 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3276 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003277 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003278 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003279 }
3280
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003281 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003282
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003283 return QCBOR_SUCCESS;
3284}
3285
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003286/*
3287 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3288 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003289static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3290{
3291 uint64_t uResult;
3292
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003293 // Take the absolute value of the mantissa and convert to unsigned.
3294 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003295 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3296
3297 // Do the exponentiation of the positive mantissa
3298 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3299 if(uReturn) {
3300 return uReturn;
3301 }
3302
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003303
Laurence Lundblade983500d2020-05-14 11:49:34 -07003304 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3305 of INT64_MIN. This assumes two's compliment representation where
3306 INT64_MIN is one increment farther from 0 than INT64_MAX.
3307 Trying to write -INT64_MIN doesn't work to get this because the
3308 compiler tries to work with an int64_t which can't represent
3309 -INT64_MIN.
3310 */
3311 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3312
3313 // Error out if too large
3314 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003315 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3316 }
3317
3318 // Casts are safe because of checks above
3319 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3320
3321 return QCBOR_SUCCESS;
3322}
3323
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003324/*
3325 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3326 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003327static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3328{
3329 if(nMantissa < 0) {
3330 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3331 }
3332
3333 // Cast to unsigned is OK because of check for negative
3334 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3335 // Exponentiation is straight forward
3336 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3337}
3338
3339
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003340#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003341
3342
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003343static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003344{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003345 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003346
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003347 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003348 const uint8_t *pByte = BigNum.ptr;
3349 size_t uLen = BigNum.len;
3350 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003351 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003352 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003353 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003354 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003355 }
3356
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003357 *pResult = uResult;
3358 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003359}
3360
Laurence Lundblade887add82020-05-17 05:50:34 -07003361static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003362{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003363 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003364}
3365
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003366static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003367{
3368 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003369 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3370 if(uError) {
3371 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003372 }
3373 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3374 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003375 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003376}
3377
3378
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003379static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003380{
3381 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003382 /* negaative int furthest from zero is INT64_MIN
3383 which is expressed as -INT64_MAX-1. The value of
3384 a negative bignum is -n-1, one further from zero
3385 than the positive bignum */
3386
3387 /* say INT64_MIN is -2; then INT64_MAX is 1.
3388 Then -n-1 <= INT64_MIN.
3389 Then -n -1 <= -INT64_MAX - 1
3390 THen n <= INT64_MAX. */
3391 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003392 if(uError) {
3393 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394 }
3395 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003396 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003397 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003398 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003399 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003400}
3401
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003402#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003403
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003404
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003405/*
3406Convert a integers and floats to an int64_t.
3407
3408\param[in] uOptions Bit mask list of conversion options.
3409
3410\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3411
3412\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3413
3414\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3415
3416*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003417static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3418{
3419 switch(pItem->uDataType) {
3420 // TODO: float when ifdefs are set
3421 case QCBOR_TYPE_DOUBLE:
3422 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3423 // TODO: what about under/overflow here?
3424 // Invokes the floating-point HW and/or compiler-added libraries
3425 feclearexcept(FE_ALL_EXCEPT);
3426 *pnValue = llround(pItem->val.dfnum);
3427 if(fetestexcept(FE_INVALID)) {
3428 // TODO: better error code
3429 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3430 }
3431 } else {
3432 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3433 }
3434 break;
3435
3436 case QCBOR_TYPE_INT64:
3437 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3438 *pnValue = pItem->val.int64;
3439 } else {
3440 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3441 }
3442 break;
3443
3444 case QCBOR_TYPE_UINT64:
3445 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3446 if(pItem->val.uint64 < INT64_MAX) {
3447 *pnValue = pItem->val.int64;
3448 } else {
3449 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3450 }
3451 } else {
3452 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3453 }
3454 break;
3455
3456 default:
3457 return QCBOR_ERR_UNEXPECTED_TYPE;
3458 }
3459 return QCBOR_SUCCESS;
3460}
3461
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003462
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003463void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3464 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003465 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003466 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003467{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003468 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003469 return;
3470 }
3471
Laurence Lundbladee6430642020-03-14 21:15:44 -07003472 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003473 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3474 if(uError) {
3475 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003476 return;
3477 }
3478
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003479 if(pItem) {
3480 *pItem = Item;
3481 }
3482
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003483 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003484}
3485
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003486
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003487void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3488 int64_t nLabel,
3489 uint32_t uOptions,
3490 int64_t *pnValue,
3491 QCBORItem *pItem)
3492{
3493 QCBORItem Item;
3494 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3495
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003496 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003497}
3498
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003499
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003500void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3501 const char * szLabel,
3502 uint32_t uOptions,
3503 int64_t *pnValue,
3504 QCBORItem *pItem)
3505{
3506 if(pMe->uLastError != QCBOR_SUCCESS) {
3507 return;
3508 }
3509
3510 QCBORItem Item;
3511 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3512
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003513 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003514}
3515
3516
3517
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003518/*
3519 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003520
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003521 \param[in] uOptions Bit mask list of conversion options.
3522
3523 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3524
3525 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3526
3527 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3528
3529 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003530static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3531{
3532 QCBORError uErr;
3533
3534 switch(pItem->uDataType) {
3535
3536 case QCBOR_TYPE_POSBIGNUM:
3537 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3538 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003539 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003540 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003541 }
3542 break;
3543
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003544 case QCBOR_TYPE_NEGBIGNUM:
3545 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3546 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003547 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003548 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003549 }
3550 break;
3551
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003552#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3553 case QCBOR_TYPE_DECIMAL_FRACTION:
3554 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3555 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3556 pItem->val.expAndMantissa.nExponent,
3557 pnValue,
3558 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003559 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003560 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3561 }
3562 break;
3563
3564 case QCBOR_TYPE_BIGFLOAT:
3565 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3566 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3567 pItem->val.expAndMantissa.nExponent,
3568 pnValue,
3569 Exponentitate2);
3570 } else {
3571 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3572 }
3573 break;
3574
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003575 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3576 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3577 int64_t nMantissa;
3578 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3579 if(uErr) {
3580 return uErr;
3581 }
3582 return ExponentiateNN(nMantissa,
3583 pItem->val.expAndMantissa.nExponent,
3584 pnValue,
3585 Exponentitate10);
3586 } else {
3587 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3588 }
3589 break;
3590
3591 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3592 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3593 int64_t nMantissa;
3594 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3595 if(uErr) {
3596 return uErr;
3597 }
3598 return ExponentiateNN(nMantissa,
3599 pItem->val.expAndMantissa.nExponent,
3600 pnValue,
3601 Exponentitate10);
3602 } else {
3603 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3604 }
3605 break;
3606
3607 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3608 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3609 int64_t nMantissa;
3610 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3611 if(uErr) {
3612 return uErr;
3613 }
3614 return ExponentiateNN(nMantissa,
3615 pItem->val.expAndMantissa.nExponent,
3616 pnValue,
3617 Exponentitate2);
3618 } else {
3619 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3620 }
3621 break;
3622
3623 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3624 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3625 int64_t nMantissa;
3626 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3627 if(uErr) {
3628 return uErr;
3629 }
3630 return ExponentiateNN(nMantissa,
3631 pItem->val.expAndMantissa.nExponent,
3632 pnValue,
3633 Exponentitate2);
3634 } else {
3635 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003636 }
3637 break;
3638
Laurence Lundbladec4537442020-04-14 18:53:22 -07003639 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640 return QCBOR_ERR_UNEXPECTED_TYPE;
3641#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003642 }
3643}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003644
3645
Laurence Lundbladec4537442020-04-14 18:53:22 -07003646/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003647 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003648 */
3649void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003650{
3651 QCBORItem Item;
3652
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003654
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003655 if(pMe->uLastError == QCBOR_SUCCESS) {
3656 // The above conversion succeeded
3657 return;
3658 }
3659
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003660 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003661 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003662 return;
3663 }
3664
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003665 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003666}
3667
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003668
3669/*
3670Public function, see header qcbor/qcbor_decode.h file
3671*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003672void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3673{
3674 QCBORItem Item;
3675
3676 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3677
3678 if(pMe->uLastError == QCBOR_SUCCESS) {
3679 // The above conversion succeeded
3680 return;
3681 }
3682
3683 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3684 // The above conversion failed in a way that code below can't correct
3685 return;
3686 }
3687
3688 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3689}
3690
3691
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003692/*
3693Public function, see header qcbor/qcbor_decode.h file
3694*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003695void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3696{
3697 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003698 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3699
3700 if(pMe->uLastError == QCBOR_SUCCESS) {
3701 // The above conversion succeeded
3702 return;
3703 }
3704
3705 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3706 // The above conversion failed in a way that code below can't correct
3707 return;
3708 }
3709
3710 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3711}
3712
3713
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003714static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3715{
3716 switch(pItem->uDataType) {
3717 // TODO: type flaot
3718 case QCBOR_TYPE_DOUBLE:
3719 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3720 feclearexcept(FE_ALL_EXCEPT);
3721 double dRounded = round(pItem->val.dfnum);
3722 // TODO: over/underflow
3723 if(fetestexcept(FE_INVALID)) {
3724 // TODO: better error code
3725 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3726 } else if(isnan(dRounded)) {
3727 // TODO: better error code
3728 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3729 } else if(dRounded >= 0) {
3730 *puValue = (uint64_t)dRounded;
3731 } else {
3732 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3733 }
3734 } else {
3735 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3736 }
3737 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003738
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003739 case QCBOR_TYPE_INT64:
3740 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3741 if(pItem->val.int64 >= 0) {
3742 *puValue = (uint64_t)pItem->val.int64;
3743 } else {
3744 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3745 }
3746 } else {
3747 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3748 }
3749 break;
3750
3751 case QCBOR_TYPE_UINT64:
3752 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3753 *puValue = pItem->val.uint64;
3754 } else {
3755 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3756 }
3757 break;
3758
3759 default:
3760 return QCBOR_ERR_UNEXPECTED_TYPE;
3761 }
3762 return QCBOR_SUCCESS;
3763}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003764
3765
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003766void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3767 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003768 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003769 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003771 if(pMe->uLastError != QCBOR_SUCCESS) {
3772 return;
3773 }
3774
Laurence Lundbladec4537442020-04-14 18:53:22 -07003775 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003776
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003777 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3778 if(uError) {
3779 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003780 return;
3781 }
3782
Laurence Lundbladea826c502020-05-10 21:07:00 -07003783 if(pItem) {
3784 *pItem = Item;
3785 }
3786
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003787 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003788}
3789
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003790
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003791void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3792{
3793 int64_t uValue;
3794 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3795 if(pMe->uLastError != QCBOR_SUCCESS) {
3796 return;
3797 }
3798
3799 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3800 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3801 }
3802}
3803
3804void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3805{
3806 int64_t uValue;
3807 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3808 if(pMe->uLastError != QCBOR_SUCCESS) {
3809 return;
3810 }
3811
3812 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3813 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3814 }
3815}
3816
3817void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3818{
3819 int64_t uValue;
3820 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3821 if(pMe->uLastError != QCBOR_SUCCESS) {
3822 return;
3823 }
3824
3825 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3826 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3827 }
3828}
3829
3830
3831
3832
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003833void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3834 int64_t nLabel,
3835 uint32_t uOptions,
3836 uint64_t *puValue,
3837 QCBORItem *pItem)
3838{
3839 QCBORItem Item;
3840 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3841
3842 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3843}
3844
3845
3846void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3847 const char * szLabel,
3848 uint32_t uOptions,
3849 uint64_t *puValue,
3850 QCBORItem *pItem)
3851{
3852 if(pMe->uLastError != QCBOR_SUCCESS) {
3853 return;
3854 }
3855
3856 QCBORItem Item;
3857 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3858
3859 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3860}
3861
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003862/*
3863 Public function, see header qcbor/qcbor_decode.h file
3864*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003865static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3866{
3867 QCBORError uErr;
3868
3869 switch(pItem->uDataType) {
3870
3871 case QCBOR_TYPE_POSBIGNUM:
3872 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3873 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3874 } else {
3875 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3876 }
3877 break;
3878
3879 case QCBOR_TYPE_NEGBIGNUM:
3880 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3881 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3882 } else {
3883 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3884 }
3885 break;
3886
3887#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3888
3889 case QCBOR_TYPE_DECIMAL_FRACTION:
3890 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3891 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3892 pItem->val.expAndMantissa.nExponent,
3893 puValue,
3894 Exponentitate10);
3895 } else {
3896 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3897 }
3898 break;
3899
3900 case QCBOR_TYPE_BIGFLOAT:
3901 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3902 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3903 pItem->val.expAndMantissa.nExponent,
3904 puValue,
3905 Exponentitate2);
3906 } else {
3907 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3908 }
3909 break;
3910
3911 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3912 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3913 // TODO: Would be better to convert to unsigned
3914 int64_t nMantissa;
3915 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3916 if(uErr != QCBOR_SUCCESS) {
3917 return uErr;
3918 }
3919 return ExponentitateNU(nMantissa,
3920 pItem->val.expAndMantissa.nExponent,
3921 puValue,
3922 Exponentitate10);
3923 } else {
3924 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3925 }
3926 break;
3927
3928 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3929 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3930 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3931 } else {
3932 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3933 }
3934 break;
3935
3936 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3937 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3938 // TODO: Would be better to convert to unsigned
3939 int64_t nMantissa;
3940 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3941 if(uErr != QCBOR_SUCCESS) {
3942 return uErr;
3943 }
3944 return ExponentitateNU(nMantissa,
3945 pItem->val.expAndMantissa.nExponent,
3946 puValue,
3947 Exponentitate2);
3948 } else {
3949 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3950 }
3951 break;
3952
3953 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3954 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3955 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3956 } else {
3957 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3958 }
3959 break;
3960#endif
3961 default:
3962 return QCBOR_ERR_UNEXPECTED_TYPE;
3963 }
3964}
3965
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003966/*
3967 Public function, see header qcbor/qcbor_decode.h file
3968*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003969void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003970{
3971 QCBORItem Item;
3972
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003973 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003974
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003975 if(pMe->uLastError == QCBOR_SUCCESS) {
3976 // The above conversion succeeded
3977 return;
3978 }
3979
3980 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3981 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003982 return;
3983 }
3984
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003985 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003986}
3987
Laurence Lundbladec4537442020-04-14 18:53:22 -07003988
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003989/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003990 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003991*/
3992void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3993{
3994 QCBORItem Item;
3995
3996 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3997
3998 if(pMe->uLastError == QCBOR_SUCCESS) {
3999 // The above conversion succeeded
4000 return;
4001 }
4002
4003 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4004 // The above conversion failed in a way that code below can't correct
4005 return;
4006 }
4007
4008 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4009}
4010
4011
4012/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004013 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004014*/
4015void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4016{
4017 QCBORItem Item;
4018 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4019
4020 if(pMe->uLastError == QCBOR_SUCCESS) {
4021 // The above conversion succeeded
4022 return;
4023 }
4024
4025 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4026 // The above conversion failed in a way that code below can't correct
4027 return;
4028 }
4029
4030 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4031}
4032
4033
4034static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4035{
4036 switch(pItem->uDataType) {
4037 // TODO: float when ifdefs are set
4038 case QCBOR_TYPE_DOUBLE:
4039 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4040 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4041 *pdValue = pItem->val.dfnum;
4042 } else {
4043 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4044 }
4045 }
4046 break;
4047
4048 case QCBOR_TYPE_INT64:
4049 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4050 // TODO: how does this work?
4051 *pdValue = (double)pItem->val.int64;
4052
4053 } else {
4054 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4055 }
4056 break;
4057
4058 case QCBOR_TYPE_UINT64:
4059 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4060 *pdValue = (double)pItem->val.uint64;
4061 } else {
4062 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4063 }
4064 break;
4065
4066 default:
4067 return QCBOR_ERR_UNEXPECTED_TYPE;
4068 }
4069
4070 return QCBOR_SUCCESS;
4071}
4072
4073
4074
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004075void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4076 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004077 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004078 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004079{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004080 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004081 return;
4082 }
4083
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004084 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004085
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004086 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004087 if(uError) {
4088 pMe->uLastError = (uint8_t)uError;
4089 return;
4090 }
4091
4092 if(pItem) {
4093 *pItem = Item;
4094 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004095
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004096 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004097}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004098
Laurence Lundbladec4537442020-04-14 18:53:22 -07004099
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004100void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4101 int64_t nLabel,
4102 uint32_t uOptions,
4103 double *pdValue,
4104 QCBORItem *pItem)
4105{
4106 QCBORItem Item;
4107 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4108
4109 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4110}
4111
4112void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4113 const char * szLabel,
4114 uint32_t uOptions,
4115 double *pdValue,
4116 QCBORItem *pItem)
4117{
4118 if(pMe->uLastError != QCBOR_SUCCESS) {
4119 return;
4120 }
4121
4122 QCBORItem Item;
4123 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4124
4125 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4126}
4127
4128
4129
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004130static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4131{
4132 double dResult;
4133
4134 dResult = 0.0;
4135 const uint8_t *pByte = BigNum.ptr;
4136 size_t uLen = BigNum.len;
4137 /* This will overflow and become the float value INFINITY if the number
4138 is too large to fit. No error will be logged.
4139 TODO: should an error be logged? */
4140 while(uLen--) {
4141 dResult = (dResult * 256.0) + (double)*pByte++;
4142 }
4143
4144 return dResult;
4145}
4146
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004147static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004148{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004149 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004150 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4151
4152 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004153 switch(pItem->uDataType) {
4154 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004155
4156#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004157 case QCBOR_TYPE_DECIMAL_FRACTION:
4158 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4159 // TODO: rounding and overflow errors
4160 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4161 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4162 } else {
4163 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4164 }
4165 break;
4166
4167 case QCBOR_TYPE_BIGFLOAT:
4168 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4169 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4170 exp2((double)pItem->val.expAndMantissa.nExponent);
4171 } else {
4172 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4173 }
4174 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004175#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004176
4177 case QCBOR_TYPE_POSBIGNUM:
4178 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4179 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4180 } else {
4181 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4182 }
4183 break;
4184
4185 case QCBOR_TYPE_NEGBIGNUM:
4186 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004187 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004188 } else {
4189 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4190 }
4191 break;
4192
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004193#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004194 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4195 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4196 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4197 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4198 } else {
4199 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4200 }
4201 break;
4202
4203 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4204 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4205 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4206 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4207 } else {
4208 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4209 }
4210 break;
4211
4212 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4213 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4214 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4215 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4216 } else {
4217 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4218 }
4219 break;
4220
4221 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4222 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004223 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004224 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4225 } else {
4226 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4227 }
4228 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004229#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4230
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004231
4232 default:
4233 return QCBOR_ERR_UNEXPECTED_TYPE;
4234 }
4235
4236 return QCBOR_SUCCESS;
4237}
4238
4239
4240/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004241 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004242*/
4243void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4244{
4245
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004246 QCBORItem Item;
4247
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004248 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004249
4250 if(pMe->uLastError == QCBOR_SUCCESS) {
4251 // The above conversion succeeded
4252 return;
4253 }
4254
4255 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4256 // The above conversion failed in a way that code below can't correct
4257 return;
4258 }
4259
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004260 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004261}
4262
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004263
4264/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004265 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004266*/
4267void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4268{
4269 QCBORItem Item;
4270
4271 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4272
4273 if(pMe->uLastError == QCBOR_SUCCESS) {
4274 // The above conversion succeeded
4275 return;
4276 }
4277
4278 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4279 // The above conversion failed in a way that code below can't correct
4280 return;
4281 }
4282
4283 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4284}
4285
4286
4287/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004288 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004289*/
4290void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4291{
4292 QCBORItem Item;
4293 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4294
4295 if(pMe->uLastError == QCBOR_SUCCESS) {
4296 // The above conversion succeeded
4297 return;
4298 }
4299
4300 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4301 // The above conversion failed in a way that code below can't correct
4302 return;
4303 }
4304
4305 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4306}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004307
4308
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004309#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004310void FarfDecimalFraction(QCBORDecodeContext *pMe,
4311 uint8_t uTagRequirement,
4312 QCBORItem *pItem,
4313 int64_t *pnMantissa,
4314 int64_t *pnExponent)
4315{
4316 QCBORError uErr;
4317
4318 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4319 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4320 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4321 return;
4322 }
4323 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4324 if(uErr != QCBOR_SUCCESS) {
4325 pMe->uLastError = (uint8_t)uErr;
4326 return;
4327 }
4328 }
4329
4330 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4331 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4332 return;
4333 }
4334
4335 switch (pItem->uDataType) {
4336
4337 case QCBOR_TYPE_DECIMAL_FRACTION:
4338 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4339 *pnExponent = pItem->val.expAndMantissa.nExponent;
4340 break;
4341
4342 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4343 *pnExponent = pItem->val.expAndMantissa.nExponent;
4344
4345 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4346 if(uErr != QCBOR_SUCCESS) {
4347 pMe->uLastError = (uint8_t)uErr;
4348 }
4349 break;
4350
4351 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4352 *pnExponent = pItem->val.expAndMantissa.nExponent;
4353
4354 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4355 if(uErr != QCBOR_SUCCESS) {
4356 pMe->uLastError = (uint8_t)uErr;
4357 }
4358 break;
4359
4360 default:
4361 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4362 }
4363}
4364
4365void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4366 uint8_t uTagRequirement,
4367 int64_t nLabel,
4368 int64_t *pnMantissa,
4369 int64_t *pnExponent)
4370{
4371 QCBORItem Item;
4372
4373 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4374 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4375}
4376
4377
4378
4379void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4380 uint8_t uTagRequirement,
4381 const char *szLabel,
4382 int64_t *pnMantissa,
4383 int64_t *pnExponent)
4384{
4385 QCBORItem Item;
4386
4387 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4388
4389 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4390}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004391#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004392
4393
4394UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4395{
4396 while(uInt & 0xff0000000000UL) {
4397 uInt = uInt << 8;
4398 };
4399
4400 UsefulOutBuf UOB;
4401
4402 UsefulOutBuf_Init(&UOB, Buffer);
4403
4404 while(uInt) {
4405 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4406 uInt = uInt << 8;
4407 }
4408
4409 return UsefulOutBuf_OutUBuf(&UOB);
4410}
4411
4412
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004413#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4414
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004415void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4416 uint8_t uTagRequirement,
4417 int64_t nLabel,
4418 UsefulBuf pBufferForMantissa,
4419 UsefulBufC *pMantissa,
4420 bool *pbIsNegative,
4421 int64_t *pnExponent)
4422{
4423 QCBORItem Item;
4424 QCBORError uErr;
4425
4426 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4427
4428 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4429 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4430 if(uErr != QCBOR_SUCCESS) {
4431 pMe->uLastError = (uint8_t)uErr;
4432 return;
4433 }
4434 }
4435
4436 uint64_t uMantissa;
4437
4438 switch (Item.uDataType) {
4439
4440 case QCBOR_TYPE_DECIMAL_FRACTION:
4441 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4442 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4443 *pbIsNegative = false;
4444 } else {
4445 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4446 *pbIsNegative = true;
4447 }
4448 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4449 *pnExponent = Item.val.expAndMantissa.nExponent;
4450 break;
4451
4452 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4453 *pnExponent = Item.val.expAndMantissa.nExponent;
4454 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4455 *pbIsNegative = false;
4456 break;
4457
4458 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4459 *pnExponent = Item.val.expAndMantissa.nExponent;
4460 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4461 *pbIsNegative = true;
4462 break;
4463
4464 default:
4465 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4466 }
4467}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004468#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004469
4470/*
4471
4472 TODO: do something with this text
4473 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4474 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4475 is the byte offset in the encoded input and a leaf counter for definite
4476 length maps and arrays. Indefinite length maps and arrays are handled
4477 by look ahead for the break.
4478
4479 The view presented to the caller has tags, labels and the chunks of
4480 indefinite length strings aggregated into one decorated data item.
4481
4482 The caller understands the nesting level in pre-order traversal by
4483 the fact that a data item that is a map or array is presented to
4484 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4485 and the nesting level of the next item.
4486
4487 The caller traverse maps and arrays in a special mode that often more convenient
4488 that tracking by nesting level. When an array or map is expected or encountered
4489 the EnterMap or EnteryArray can be called.
4490
4491 When entering a map or array like this, the cursor points to the first
4492 item in the map or array. When exiting, it points to the item after
4493 the map or array, regardless of whether the items in the map or array were
4494 all traversed.
4495
4496 When in a map or array, the cursor functions as normal, but traversal
4497 cannot go past the end of the map or array that was entered. If this
4498 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4499 go past the end of the map or array ExitMap() or ExitArray() must
4500 be called. It can be called any time regardless of the position
4501 of the cursor.
4502
4503 When a map is entered, a special function allows fetching data items
4504 by label. This call will traversal the whole map looking for the
4505 labeled item. The whole map is traversed so as to detect duplicates.
4506 This type of fetching items does not affect the normal traversal
4507 cursor.
4508
4509
4510 When a data item is presented to the caller, the nesting level of the data
4511 item is presented along with the nesting level of the item that would be
4512 next consumed.
4513 */