blob: 902c92467e0a99f5be44ca11d721be9012748939 [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
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700180 /*
181 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
182 larger than DecodeNesting_EnterBoundedMode which keeps it less than
183 uin32_t so the cast is safe.
184 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
186}
187
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700188
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700189inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700191 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700192}
193
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700194
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700195inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700196DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700197{
198 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700199 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700200 return false;
201 }
202 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700203 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700204 return false;
205 }
206 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700207 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700208 return false;
209 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700210 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700211 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700213 return false;
214 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216 return true;
217}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700218
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700220inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700221DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
225 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700226 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700227 return false;
228 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700229}
230
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700231
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700232inline static bool
233DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700234{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700235 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
236 return true;
237 } else {
238 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700239 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240}
241
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700242
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700243inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700245{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700246 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700247 return false;
248 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700249
250 if(pNesting->pCurrentBounded->uLevelType != uType) {
251 return false;
252 }
253
254 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700255}
256
Laurence Lundblade02625d42020-06-25 14:41:41 -0700257
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700258inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700259DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700260{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700261 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700263}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700264
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700265
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700266inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700267DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
268{
269 // Only call on a defnite length array / map
270 pNesting->pCurrent->u.ma.uCountCursor++;
271}
272
273
274inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700275DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
276{
277 pNesting->pCurrent--;
278}
279
Laurence Lundblade02625d42020-06-25 14:41:41 -0700280
281static QCBORError
282DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
283{
284 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700285 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700286 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
287 }
288
289 // The actual descend
290 pNesting->pCurrent++;
291
292 pNesting->pCurrent->uLevelType = uType;
293
294 return QCBOR_SUCCESS;
295}
296
297
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700298inline static QCBORError
299DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700300{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700301 /*
302 Should only be called on map/array.
303
304 Have descended into this before this is called. The job here is
305 just to mark it in bounded mode.
306 */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700307 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
308 return QCBOR_ERR_BUFFER_TOO_LARGE;
309 }
310
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700311 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700312 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700313
314 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700315}
316
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700317
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700318inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700319DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 uint8_t uQCBORType,
321 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700322{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700324
325 if(uCount == 0) {
326 // Nothing to do for empty definite lenth arrays. They are just are
327 // effectively the same as an item that is not a map or array
328 goto Done;
329 // Empty indefinite length maps and arrays are handled elsewhere
330 }
331
332 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700333 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
334 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
335 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700336 goto Done;
337 }
338
Laurence Lundblade02625d42020-06-25 14:41:41 -0700339 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
340 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341 goto Done;
342 }
343
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700345 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
346 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700347
348 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349
350Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700351 return uError;;
352}
353
354
355static inline void
356DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
357{
358 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
359}
360
361
362static inline void
363DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
364{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700365 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700366 pNesting->pCurrentBounded--;
367 if(DecodeNesting_IsCurrentBounded(pNesting)) {
368 break;
369 }
370 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700371}
372
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700373static inline void
374DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
375{
376 pNesting->pCurrent = pNesting->pCurrentBounded;
377}
378
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700379
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700380inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700381DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
382 size_t uEndOffset,
383 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700385 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700386
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
388 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389 goto Done;
390 }
391
Laurence Lundblade02625d42020-06-25 14:41:41 -0700392 // Fill in the new byte string level
393 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700394 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700395 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700396
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700398 pNesting->pCurrentBounded = pNesting->pCurrent;
399
400Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700401 return uError;;
402}
403
Laurence Lundbladed0304932020-06-27 10:59:38 -0700404
405static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700406DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407{
408 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700409}
410
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700411
Laurence Lundbladeee851742020-01-08 08:37:05 -0800412inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
417 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418}
419
420
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700421inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700423{
424 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700425 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700426 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700427}
428
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700431DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700432{
433 *pNesting = *pSave;
434}
435
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700436
Laurence Lundblade02625d42020-06-25 14:41:41 -0700437static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700438DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700439{
440 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
441}
442
443
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700445DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446{
447 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
448}
449
450
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700452
453const char *TypeStr(uint8_t type)
454{
455 switch(type) {
456 case QCBOR_TYPE_MAP: return " map";
457 case QCBOR_TYPE_ARRAY: return "array";
458 case QCBOR_TYPE_BYTE_STRING: return " bstr";
459 default: return " --- ";
460 }
461}
462
463static char buf[20]; // Not thread safe, but that is OK
464const char *CountString(uint16_t uCount, uint16_t uTotal)
465{
466 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
467 strcpy(buf, "indefinite");
468 } else {
469 sprintf(buf, "%d/%d", uCount, uTotal);
470 }
471 return buf;
472}
473
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700476{
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700477 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700478 szName,
479 (uint32_t)pBuf->cursor,
480 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700481
482 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700483 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700484 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 break;
486 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700487
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700488 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700490 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700491 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700492
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700493 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700495 pNesting->pLevels[i].u.bs.uEndOfBstr,
496 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700497
498 } else {
499 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700500 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
501 pNesting->pLevels[i].u.ma.uCountTotal));
502 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
503 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700504 }
505 }
506
507 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700508 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700509 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700510}
511
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700512
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
516
517 The following four functions are pretty wrappers for invocation of
518 the string allocator supplied by the caller.
519
Laurence Lundbladeee851742020-01-08 08:37:05 -0800520 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline void
523StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528// StringAllocator_Reallocate called with pMem NULL is
529// equal to StringAllocator_Allocate()
530static inline UsefulBuf
531StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
532 void *pMem,
533 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534{
535 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
536}
537
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538static inline UsefulBuf
539StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540{
541 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
542}
543
Laurence Lundbladeee851742020-01-08 08:37:05 -0800544static inline void
545StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546{
547 if(pMe->pfAllocator) {
548 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
549 }
550}
551
552
553
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554/*===========================================================================
555 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800557 See qcbor/qcbor_decode.h for definition of the object
558 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800559 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700560/*
561 Public function, see header file
562 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800563void QCBORDecode_Init(QCBORDecodeContext *me,
564 UsefulBufC EncodedCBOR,
565 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700566{
567 memset(me, 0, sizeof(QCBORDecodeContext));
568 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800569 // Don't bother with error check on decode mode. If a bad value is
570 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700571 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700572 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700573 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700574 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700575 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576}
577
578
579/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580 Public function, see header file
581 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
583 QCBORStringAllocate pfAllocateFunction,
584 void *pAllocateContext,
585 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
588 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
589 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700590}
591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592
593/*
594 Public function, see header file
595 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700596void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700598{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700599 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700600 (void)pMe;
601 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602}
603
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
605/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800606 This decodes the fundamental part of a CBOR data item, the type and
607 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeee851742020-01-08 08:37:05 -0800611 This does the network->host byte order conversion. The conversion
612 here also results in the conversion for floats in addition to that
613 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800614
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700615 This returns:
616 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800617
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800618 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619 tags and floats and length for strings and arrays
620
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800622 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800623
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 The int type is preferred to uint8_t for some variables as this
625 avoids integer promotions, can reduce code size and makes
626 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
629 int *pnMajorType,
630 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700633 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800637
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 const int nTmpMajorType = nInitialByte >> 5;
640 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800641
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // Where the number or argument accumulates
643 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800644
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700646 // Need to get 1,2,4 or 8 additional argument bytes. Map
647 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800648 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800650 // Loop getting all the bytes in the argument
651 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800653 // This shift and add gives the endian conversion
654 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
655 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800657 // The reserved and thus-far unused additional info values
658 nReturn = QCBOR_ERR_UNSUPPORTED;
659 goto Done;
660 } else {
661 // Less than 24, additional info is argument or 31, an indefinite length
662 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 if(UsefulInputBuf_GetError(pUInBuf)) {
667 nReturn = QCBOR_ERR_HIT_END;
668 goto Done;
669 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671 // All successful if we got here.
672 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800673 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800674 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677Done:
678 return nReturn;
679}
680
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800683 CBOR doesn't explicitly specify two's compliment for integers but all
684 CPUs use it these days and the test vectors in the RFC are so. All
685 integers in the CBOR structure are positive and the major type
686 indicates positive or negative. CBOR can express positive integers
687 up to 2^x - 1 where x is the number of bits and negative integers
688 down to 2^x. Note that negative numbers can be one more away from
689 zero than positive. Stdint, as far as I can tell, uses two's
690 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 used carefully here, and in particular why it isn't used in the interface.
694 Also see
695 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
696
697 Int is used for values that need less than 16-bits and would be subject
698 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800700inline static QCBORError
701DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700702{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700703 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700705 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
706 if (uNumber <= INT64_MAX) {
707 pDecodedItem->val.int64 = (int64_t)uNumber;
708 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 } else {
711 pDecodedItem->val.uint64 = uNumber;
712 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 }
715 } else {
716 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800717 // CBOR's representation of negative numbers lines up with the
718 // two-compliment representation. A negative integer has one
719 // more in range than a positive integer. INT64_MIN is
720 // equal to (-INT64_MAX) - 1.
721 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 } else {
725 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000726 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 nReturn = QCBOR_ERR_INT_OVERFLOW;
728 }
729 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800730
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700731 return nReturn;
732}
733
734// Make sure #define value line up as DecodeSimple counts on this.
735#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
736#error QCBOR_TYPE_FALSE macro value wrong
737#endif
738
739#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
740#error QCBOR_TYPE_TRUE macro value wrong
741#endif
742
743#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
744#error QCBOR_TYPE_NULL macro value wrong
745#endif
746
747#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
748#error QCBOR_TYPE_UNDEF macro value wrong
749#endif
750
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700751#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
752#error QCBOR_TYPE_BREAK macro value wrong
753#endif
754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
756#error QCBOR_TYPE_DOUBLE macro value wrong
757#endif
758
759#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
760#error QCBOR_TYPE_FLOAT macro value wrong
761#endif
762
763/*
764 Decode true, false, floats, break...
765 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800766inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800767DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700769 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800770
Laurence Lundbladeee851742020-01-08 08:37:05 -0800771 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 // above make sure uAdditionalInfo values line up with uDataType values.
773 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
774 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800777 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
778 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700780 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700781 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
782 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700783 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700784 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700785 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
786 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700787 break;
788 case DOUBLE_PREC_FLOAT:
789 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700790 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 case CBOR_SIMPLEV_FALSE: // 20
794 case CBOR_SIMPLEV_TRUE: // 21
795 case CBOR_SIMPLEV_NULL: // 22
796 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700797 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 case CBOR_SIMPLEV_ONEBYTE: // 24
801 if(uNumber <= CBOR_SIMPLE_BREAK) {
802 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700803 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700804 goto Done;
805 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800806 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800808
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 default: // 0-19
810 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800811 /*
812 DecodeTypeAndNumber will make uNumber equal to
813 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
814 safe because the 2, 4 and 8 byte lengths of uNumber are in
815 the double/float cases above
816 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 pDecodedItem->val.uSimple = (uint8_t)uNumber;
818 break;
819 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800820
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821Done:
822 return nReturn;
823}
824
825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530827 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800829inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
830 int nMajorType,
831 uint64_t uStrLen,
832 UsefulInputBuf *pUInBuf,
833 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700835 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800837 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
838 // This check makes the casts to size_t below safe.
839
840 // 4 bytes less than the largest sizeof() so this can be tested by
841 // putting a SIZE_MAX length in the CBOR test input (no one will
842 // care the limit on strings is 4 bytes shorter).
843 if(uStrLen > SIZE_MAX-4) {
844 nReturn = QCBOR_ERR_STRING_TOO_LONG;
845 goto Done;
846 }
847
848 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530849 if(UsefulBuf_IsNULLC(Bytes)) {
850 // Failed to get the bytes for this string item
851 nReturn = QCBOR_ERR_HIT_END;
852 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530854
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800855 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530856 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530858 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700859 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530860 goto Done;
861 }
862 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800863 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530864 } else {
865 // Normal case with no string allocator
866 pDecodedItem->val.string = Bytes;
867 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800868 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800869 // Cast because ternary operator causes promotion to integer
870 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
871 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800872
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530873Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874 return nReturn;
875}
876
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879
880
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881
882
Laurence Lundbladeee851742020-01-08 08:37:05 -0800883// Make sure the constants align as this is assumed by
884// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
886#error QCBOR_TYPE_ARRAY value not lined up with major type
887#endif
888#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
889#error QCBOR_TYPE_MAP value not lined up with major type
890#endif
891
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700892/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800893 This gets a single data item and decodes it including preceding
894 optional tagging. This does not deal with arrays and maps and nesting
895 except to decode the data item introducing them. Arrays and maps are
896 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladeee851742020-01-08 08:37:05 -0800898 Errors detected here include: an array that is too long to decode,
899 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800901static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
902 QCBORItem *pDecodedItem,
903 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700905 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladeee851742020-01-08 08:37:05 -0800907 /*
908 Get the major type and the number. Number could be length of more
909 bytes or the value depending on the major type nAdditionalInfo is
910 an encoding of the length of the uNumber and is needed to decode
911 floats and doubles
912 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800913 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800915 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700917 memset(pDecodedItem, 0, sizeof(QCBORItem));
918
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800919 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800920
Laurence Lundbladeee851742020-01-08 08:37:05 -0800921 // Error out here if we got into trouble on the type and number. The
922 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700923 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700925 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 // At this point the major type and the value are valid. We've got
928 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800929 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
931 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800932 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700933 nReturn = QCBOR_ERR_BAD_INT;
934 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800935 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700936 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700939 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
940 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800941 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
942 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
943 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
944 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530945 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700946 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 }
949 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
952 case CBOR_MAJOR_TYPE_MAP: // Major type 5
953 // Record the number of items in the array or map
954 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
955 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
956 goto Done;
957 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700959 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800961 // type conversion OK because of check above
962 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800964 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
966 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800970 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700971 nReturn = QCBOR_ERR_BAD_INT;
972 } else {
973 pDecodedItem->val.uTagV = uNumber;
974 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
975 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundbladeee851742020-01-08 08:37:05 -0800978 case CBOR_MAJOR_TYPE_SIMPLE:
979 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800980 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundbladeee851742020-01-08 08:37:05 -0800983 default:
984 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 nReturn = QCBOR_ERR_UNSUPPORTED;
986 break;
987 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989Done:
990 return nReturn;
991}
992
993
994
995/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800996 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800997 individual chunk items together into one QCBORItem using the string
998 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301000 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001002static inline QCBORError
1003GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001005 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001006
1007 // Get pointer to string allocator. First use is to pass it to
1008 // GetNext_Item() when option is set to allocate for *every* string.
1009 // Second use here is to allocate space to coallese indefinite
1010 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001011 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1012 &(me->StringAllocator) :
1013 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001014
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001015 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001016 nReturn = GetNext_Item(&(me->InBuf),
1017 pDecodedItem,
1018 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 if(nReturn) {
1020 goto Done;
1021 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301024 // code in this function from here down can be eliminated. Run tests, except
1025 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001027 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001028 const uint8_t uStringType = pDecodedItem->uDataType;
1029 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 goto Done; // no need to do any work here on non-string types
1031 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001033 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301034 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001035 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301038 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001039 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001040 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1041 goto Done;
1042 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001044 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001045 UsefulBufC FullString = NULLUsefulBufC;
1046
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001048 // Get item for next chunk
1049 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001050 // NULL string allocator passed here. Do not need to allocate
1051 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001052 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001054 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301057 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001058 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001059 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301061 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062 break;
1063 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001065 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301066 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001067 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001068 if(StringChunkItem.uDataType != uStringType ||
1069 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001070 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 break;
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301074 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001075 // The first time throurgh FullString.ptr is NULL and this is
1076 // equivalent to StringAllocator_Allocate()
1077 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1078 UNCONST_POINTER(FullString.ptr),
1079 FullString.len + StringChunkItem.val.string.len);
1080
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301082 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001083 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 break;
1085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001087 // Copy new string chunk at the end of string so far.
1088 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001091 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1092 // Getting the item failed, clean up the allocated memory
1093 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001094 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001096Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001097 return nReturn;
1098}
1099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001100
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001101static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1102 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001103 return uTagVal;
1104 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001105 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001106 return me->auMappedTags[x];
1107 }
1108}
1109
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001110/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001111 Gets all optional tag data items preceding a data item that is not an
1112 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001113 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001114static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001115GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001116{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001117 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001118
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001119 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1120 CBOR_TAG_INVALID16,
1121 CBOR_TAG_INVALID16,
1122 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001123
Laurence Lundblade59289e52019-12-30 13:44:37 -08001124 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001125 for(;;) {
1126 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001127 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001128 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001129 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001131 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1132 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134 break;
1135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001136
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001137 // Is there room for the tag in the tags list?
1138 size_t uTagIndex;
1139 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001140 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001141 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001142 }
1143 }
1144 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001145 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001147
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001149 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001150 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001151 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001152 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001153 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001154 break;
1155 }
1156 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001157 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001158 break;
1159 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001160 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001161 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1162 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001163 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1164 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001165 }
1166
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001167 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170
1171 } else {
1172 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001173 }
1174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176Done:
1177 return nReturn;
1178}
1179
1180
1181/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001182 This layer takes care of map entries. It combines the label and data
1183 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001184 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001185static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001187{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001188 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001189 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001190 if(nReturn)
1191 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001193 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001194 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001195 goto Done;
1196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001198 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1199 // In a map and caller wants maps decoded, not treated as arrays
1200
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001201 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001202 // If in a map and the right decoding mode, get the label
1203
Laurence Lundbladeee851742020-01-08 08:37:05 -08001204 // Save label in pDecodedItem and get the next which will
1205 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001206 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001208 if(nReturn)
1209 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301211 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001212
1213 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1214 // strings are always good labels
1215 pDecodedItem->label.string = LabelItem.val.string;
1216 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1217 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001218 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001219 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1220 goto Done;
1221 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1222 pDecodedItem->label.int64 = LabelItem.val.int64;
1223 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1224 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1225 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1226 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1227 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1228 pDecodedItem->label.string = LabelItem.val.string;
1229 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1230 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1231 } else {
1232 // label is not an int or a string. It is an arrray
1233 // or a float or such and this implementation doesn't handle that.
1234 // Also, tags on labels are ignored.
1235 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1236 goto Done;
1237 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001238 }
1239 } else {
1240 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001241 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1242 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1243 goto Done;
1244 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001245 // Decoding a map as an array
1246 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001247 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1248 // Cast is needed because of integer promotion
1249 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 }
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001253Done:
1254 return nReturn;
1255}
1256
1257
Laurence Lundblade02625d42020-06-25 14:41:41 -07001258/*
1259 See if next item is a CBOR break. If it is, it is consumed,
1260 if not it is not consumed.
1261*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001262static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001263NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1264{
1265 *pbNextIsBreak = false;
1266 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001267 QCBORItem Peek;
1268 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1269 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1270 if(uReturn != QCBOR_SUCCESS) {
1271 return uReturn;
1272 }
1273 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001274 // It is not a break, rewind so it can be processed normally.
1275 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001276 } else {
1277 *pbNextIsBreak = true;
1278 }
1279 }
1280
1281 return QCBOR_SUCCESS;
1282}
1283
1284
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001286 An item was just consumed, now figure out if it was the
1287 end of an array or map that can be closed out. That
1288 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001289*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001290static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001291{
1292 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001293
Laurence Lundblade642282a2020-06-23 12:00:33 -07001294 /* This loops ascending nesting levels as long as there is ascending to do */
1295 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1296
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001297 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001298 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001299 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1300 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001301 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001302 break;
1303 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001304 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001305
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001306 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001307 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001308 bool bIsBreak = false;
1309 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1310 if(uReturn != QCBOR_SUCCESS) {
1311 goto Done;
1312 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001313
1314 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001315 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001316 break;
1317 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001318
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001319 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001320 /*
1321 Break occurred inside a bstr-wrapped CBOR or
1322 in the top level sequence. This is always an
1323 error because neither are an indefinte length
1324 map/array.
1325 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001326 uReturn = QCBOR_ERR_BAD_BREAK;
1327 goto Done;
1328 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001329 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001330 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331
Laurence Lundblade02625d42020-06-25 14:41:41 -07001332 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001333
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001335 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336 /* 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 -07001337 if(bMarkEnd) {
1338 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001339 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001340
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001341 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001342 break;
1343 }
1344
1345 /* Finally, actually ascend one level. */
1346 DecodeNesting_Ascend(&(pMe->nesting));
1347 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001348
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001349 uReturn = QCBOR_SUCCESS;
1350
1351Done:
1352 return uReturn;
1353}
1354
1355
1356/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001357 This the travesal going descending into and asecnding out of maps,
1358 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1359 indefinte length maps and arrays by looking at the item count or
1360 finding CBOR breaks. It detects the ends of the top-level sequence
1361 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001362 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001363static QCBORError
1364QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001365{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001366 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001367 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001368
Laurence Lundblade642282a2020-06-23 12:00:33 -07001369 /*
1370 If out of bytes to consume, it is either the end of the top-level
1371 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001372
Laurence Lundblade642282a2020-06-23 12:00:33 -07001373 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1374 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1375 CBOR is exited, the length is set back to the top-level's length
1376 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001377
Laurence Lundblade642282a2020-06-23 12:00:33 -07001378 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1379 when at the top level to allow other code below to process various
1380 errors when out of bytes to decode and not at the top level. Note
1381 that QCBORDecode_Finish() still needs to be called to be sure all
1382 nesting levels were closed out.
1383 */
1384 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1385 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001386 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001387 goto Done;
1388 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001389
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 /*
1391 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001392 array. The check for the end of an indefinite length array is
1393 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001394 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001395 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001397 goto Done;
1398 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001399
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001401 uReturn = GetNext_MapEntry(me, pDecodedItem);
1402 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001403 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001404 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301405
Laurence Lundblade642282a2020-06-23 12:00:33 -07001406 /*
1407 Breaks ending arrays/maps are always processed at the end of this
1408 function. They should never show up here.
1409 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301410 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001411 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301412 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301413 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001414
Laurence Lundblade642282a2020-06-23 12:00:33 -07001415 /*
1416 Record the nesting level for this data item before processing any
1417 of decrementing and descending.
1418 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001419 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001420
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421
1422 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001423 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001424 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426
Laurence Lundblade02625d42020-06-25 14:41:41 -07001427 Empty maps and arrays descended into, but then ascended out
1428 of in the next chunk of code.
1429
1430 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001431 encloses them so a decrement needs to be done for them too, but
1432 that is done only when all the items in them have been
1433 processed, not when they are opened with the exception of an
1434 empty map or array.
1435 */
1436 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1437 pDecodedItem->uDataType,
1438 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001439 if(uReturn != QCBOR_SUCCESS) {
1440 goto Done;
1441 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001442 }
1443
Laurence Lundblade02625d42020-06-25 14:41:41 -07001444 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1445 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1446 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447 /*
1448 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001449 - A non-aggregate like an integer or string
1450 - An empty definite length map or array
1451 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001452
1453 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 definite length map/array and break detection for an indefinite
1455 length map/array. If the end of the map/array was reached, then
1456 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001457 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001458 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001459 if(uReturn) {
1460 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001461 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301462 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001463
Laurence Lundblade02625d42020-06-25 14:41:41 -07001464 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 Tell the caller what level is next. This tells them what
1467 maps/arrays were closed out and makes it possible for them to
1468 reconstruct the tree with just the information returned in
1469 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001470 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001471 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001472 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001473 pDecodedItem->uNextNestLevel = 0;
1474 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001475 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001478Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001479 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001480 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001481 memset(pDecodedItem, 0, sizeof(QCBORItem));
1482 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001483 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001484}
1485
1486
Laurence Lundblade59289e52019-12-30 13:44:37 -08001487/*
1488 Mostly just assign the right data type for the date string.
1489 */
1490inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1491{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001492 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1493 return QCBOR_ERR_BAD_OPT_TAG;
1494 }
1495
1496 const UsefulBufC Temp = pDecodedItem->val.string;
1497 pDecodedItem->val.dateString = Temp;
1498 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1499 return QCBOR_SUCCESS;
1500}
1501
1502
1503/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001504 The epoch formatted date. Turns lots of different forms of encoding
1505 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001506 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001507static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001508{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001509 QCBORError nReturn = QCBOR_SUCCESS;
1510
1511 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1512
1513 switch (pDecodedItem->uDataType) {
1514
1515 case QCBOR_TYPE_INT64:
1516 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1517 break;
1518
1519 case QCBOR_TYPE_UINT64:
1520 if(pDecodedItem->val.uint64 > INT64_MAX) {
1521 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1522 goto Done;
1523 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001524 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001525 break;
1526
1527 case QCBOR_TYPE_DOUBLE:
1528 {
1529 // This comparison needs to be done as a float before
1530 // conversion to an int64_t to be able to detect doubles
1531 // that are too large to fit into an int64_t. A double
1532 // has 52 bits of preceision. An int64_t has 63. Casting
1533 // INT64_MAX to a double actually causes a round up which
1534 // is bad and wrong for the comparison because it will
1535 // allow conversion of doubles that can't fit into a
1536 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1537 // the cutoff point as if that rounds up in conversion to
1538 // double it will still be less than INT64_MAX. 0x7ff is
1539 // picked because it has 11 bits set.
1540 //
1541 // INT64_MAX seconds is on the order of 10 billion years,
1542 // and the earth is less than 5 billion years old, so for
1543 // most uses this conversion error won't occur even though
1544 // doubles can go much larger.
1545 //
1546 // Without the 0x7ff there is a ~30 minute range of time
1547 // values 10 billion years in the past and in the future
1548 // where this this code would go wrong.
1549 const double d = pDecodedItem->val.dfnum;
1550 if(d > (double)(INT64_MAX - 0x7ff)) {
1551 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1552 goto Done;
1553 }
1554 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1555 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1556 }
1557 break;
1558
1559 default:
1560 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1561 goto Done;
1562 }
1563 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1564
1565Done:
1566 return nReturn;
1567}
1568
1569
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001570/*
1571 Mostly just assign the right data type for the bignum.
1572 */
1573inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1574{
1575 // Stack Use: UsefulBuf 1 -- 16
1576 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1577 return QCBOR_ERR_BAD_OPT_TAG;
1578 }
1579 const UsefulBufC Temp = pDecodedItem->val.string;
1580 pDecodedItem->val.bigNum = Temp;
1581 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1582 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1583 : QCBOR_TYPE_NEGBIGNUM);
1584 return QCBOR_SUCCESS;
1585}
1586
1587
Laurence Lundblade59289e52019-12-30 13:44:37 -08001588#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1589/*
1590 Decode decimal fractions and big floats.
1591
1592 When called pDecodedItem must be the array that is tagged as a big
1593 float or decimal fraction, the array that has the two members, the
1594 exponent and mantissa.
1595
1596 This will fetch and decode the exponent and mantissa and put the
1597 result back into pDecodedItem.
1598 */
1599inline static QCBORError
1600QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1601{
1602 QCBORError nReturn;
1603
1604 // --- Make sure it is an array; track nesting level of members ---
1605 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1606 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1607 goto Done;
1608 }
1609
1610 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001611 // definite length arrays, but not for indefnite. Instead remember
1612 // the nesting level the two integers must be at, which is one
1613 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001614 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1615
1616 // --- Is it a decimal fraction or a bigfloat? ---
1617 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1618 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1619
1620 // --- Get the exponent ---
1621 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001622 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001623 if(nReturn != QCBOR_SUCCESS) {
1624 goto Done;
1625 }
1626 if(exponentItem.uNestingLevel != nNestLevel) {
1627 // Array is empty or a map/array encountered when expecting an int
1628 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1629 goto Done;
1630 }
1631 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1632 // Data arriving as an unsigned int < INT64_MAX has been converted
1633 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1634 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1635 // will be too large for this to handle and thus an error that will
1636 // get handled in the next else.
1637 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1638 } else {
1639 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1640 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1641 goto Done;
1642 }
1643
1644 // --- Get the mantissa ---
1645 QCBORItem mantissaItem;
1646 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1647 if(nReturn != QCBOR_SUCCESS) {
1648 goto Done;
1649 }
1650 if(mantissaItem.uNestingLevel != nNestLevel) {
1651 // Mantissa missing or map/array encountered when expecting number
1652 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1653 goto Done;
1654 }
1655 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1656 // Data arriving as an unsigned int < INT64_MAX has been converted
1657 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1658 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1659 // will be too large for this to handle and thus an error that
1660 // will get handled in an else below.
1661 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1662 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1663 // Got a good big num mantissa
1664 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1665 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001666 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1667 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1668 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001669 } else {
1670 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1671 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1672 goto Done;
1673 }
1674
1675 // --- Check that array only has the two numbers ---
1676 if(mantissaItem.uNextNestLevel == nNestLevel) {
1677 // Extra items in the decimal fraction / big num
1678 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1679 goto Done;
1680 }
1681
1682Done:
1683
1684 return nReturn;
1685}
1686#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1687
1688
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001689
1690/*
1691 */
1692inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1693{
1694 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1695 return QCBOR_ERR_BAD_OPT_TAG;
1696 }
1697 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1698 return QCBOR_SUCCESS;
1699}
1700
1701
1702inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1703{
1704 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1705 return QCBOR_ERR_BAD_OPT_TAG;
1706 }
1707 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1708 return QCBOR_SUCCESS;
1709}
1710
1711
1712inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1713{
1714 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1715 return QCBOR_ERR_BAD_OPT_TAG;
1716 }
1717 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1718 return QCBOR_SUCCESS;
1719}
1720
1721
1722inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1723{
1724 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1725 return QCBOR_ERR_BAD_OPT_TAG;
1726 }
1727 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1728 return QCBOR_SUCCESS;
1729}
1730
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001731inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1732{
1733 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1734 return QCBOR_ERR_BAD_OPT_TAG;
1735 }
1736 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1737 return QCBOR_SUCCESS;
1738}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001739
1740inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1741{
1742 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1743 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1744 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1745 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1746 } else {
1747 return QCBOR_ERR_BAD_OPT_TAG;
1748 }
1749 return QCBOR_SUCCESS;
1750}
1751
1752
1753/*
1754 */
1755inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1756{
1757 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1758 return QCBOR_ERR_BAD_OPT_TAG;
1759 }
1760 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1761 return QCBOR_SUCCESS;
1762}
1763
1764
Laurence Lundblade59289e52019-12-30 13:44:37 -08001765/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001766 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001768QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001769QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001770{
1771 QCBORError nReturn;
1772
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001773 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001774 if(nReturn != QCBOR_SUCCESS) {
1775 goto Done;
1776 }
1777
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001778 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1779 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001780
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001781 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001782 nReturn = DecodeDateString(pDecodedItem);
1783 break;
1784
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001785 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001786 nReturn = DecodeDateEpoch(pDecodedItem);
1787 break;
1788
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001789 case CBOR_TAG_POS_BIGNUM:
1790 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001791 nReturn = DecodeBigNum(pDecodedItem);
1792 break;
1793
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001794 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1795 case CBOR_TAG_DECIMAL_FRACTION:
1796 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001797 // For aggregate tagged types, what goes into pTags is only collected
1798 // from the surrounding data item, not the contents, so pTags is not
1799 // passed on here.
1800
1801 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1802 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001803 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001804
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001805 case CBOR_TAG_CBOR:
1806 nReturn = DecodeWrappedCBOR(pDecodedItem);
1807 break;
1808
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001809 case CBOR_TAG_URI:
1810 nReturn = DecodeURI(pDecodedItem);
1811 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001812
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001813 case CBOR_TAG_B64URL:
1814 nReturn = DecodeB64URL(pDecodedItem);
1815 break;
1816
1817 case CBOR_TAG_B64:
1818 nReturn = DecodeB64(pDecodedItem);
1819 break;
1820
1821 case CBOR_TAG_MIME:
1822 case CBOR_TAG_BINARY_MIME:
1823 nReturn = DecodeMIME(pDecodedItem);
1824 break;
1825
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001826 case CBOR_TAG_REGEX:
1827 nReturn = DecodeRegex(pDecodedItem);
1828 break;
1829
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001830 case CBOR_TAG_BIN_UUID:
1831 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001832 break;
1833
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001834 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001835 // The end of the tag list or no tags
1836 // Successful exit from the loop.
1837 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001838
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001839 default:
1840 // A tag that is not understood
1841 // A successful exit from the loop
1842 goto Done;
1843
1844 }
1845 if(nReturn != QCBOR_SUCCESS) {
1846 goto Done;
1847 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001848 }
1849
1850Done:
1851 if(nReturn != QCBOR_SUCCESS) {
1852 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1853 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1854 }
1855 return nReturn;
1856}
1857
1858
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001859QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1860{
1861 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1862
1863 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1864
1865 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1866
1867 return uErr;
1868}
1869
1870
Laurence Lundblade59289e52019-12-30 13:44:37 -08001871/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001872 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001873 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001874QCBORError
1875QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1876 QCBORItem *pDecodedItem,
1877 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001878{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001879 QCBORError nReturn;
1880
1881 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1882 if(nReturn != QCBOR_SUCCESS) {
1883 return nReturn;
1884 }
1885
1886 if(pTags != NULL) {
1887 pTags->uNumUsed = 0;
1888 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001889 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001890 break;
1891 }
1892 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1893 return QCBOR_ERR_TOO_MANY_TAGS;
1894 }
1895 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1896 pTags->uNumUsed++;
1897 }
1898 }
1899
1900 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001901}
1902
1903
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001904/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301905 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301906 next one down. If a layer has no work to do for a particular item
1907 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001908
Laurence Lundblade59289e52019-12-30 13:44:37 -08001909 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1910 tagged data items, turning them into the local C representation.
1911 For the most simple it is just associating a QCBOR_TYPE with the data. For
1912 the complex ones that an aggregate of data items, there is some further
1913 decoding and a little bit of recursion.
1914
1915 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301916 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301917 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001918 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001919
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301920 - GetNext_MapEntry -- This handles the combining of two
1921 items, the label and the data, that make up a map entry.
1922 It only does work on maps. It combines the label and data
1923 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001924
Laurence Lundblade59289e52019-12-30 13:44:37 -08001925 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1926 tags into bit flags associated with the data item. No actual decoding
1927 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001928
Laurence Lundblade59289e52019-12-30 13:44:37 -08001929 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301930 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301931 string allocater to create contiguous space for the item. It
1932 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001933
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1935 atomic data item has a "major type", an integer "argument" and optionally
1936 some content. For text and byte strings, the content is the bytes
1937 that make up the string. These are the smallest data items that are
1938 considered to be well-formed. The content may also be other data items in
1939 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001940
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001941 Roughly this takes 300 bytes of stack for vars. Need to
1942 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001943
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301944 */
1945
1946
1947/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001948 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001949 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001950int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001951 const QCBORItem *pItem,
1952 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001953{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001954 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001955 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001956 break;
1957 }
1958 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1959 return 1;
1960 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001961 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001962
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001963 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001964}
1965
1966
1967/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001968 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001969 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001970QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001971{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001972 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001973
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001974 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001975 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001976 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1977 goto Done;
1978 }
1979
1980 // Error out if not all the bytes are consumed
1981 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1982 nReturn = QCBOR_ERR_EXTRA_BYTES;
1983 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001984
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001985Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301986 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001987 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001988 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001989
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001990 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001991}
1992
1993
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001994/*
1995Public function, see header qcbor/qcbor_decode.h file
1996*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001997uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1998 const QCBORItem *pItem,
1999 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002000{
2001 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2002 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002003 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002004 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002005 }
2006}
2007
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002008
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002009/*
2010
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002011Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002012
Laurence Lundbladeee851742020-01-08 08:37:05 -08002013 - Hit end of input before it was expected while decoding type and
2014 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002015
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002016 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002017
Laurence Lundbladeee851742020-01-08 08:37:05 -08002018 - Hit end of input while decoding a text or byte string
2019 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundbladeee851742020-01-08 08:37:05 -08002021 - Encountered conflicting tags -- e.g., an item is tagged both a date
2022 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023
Laurence Lundbladeee851742020-01-08 08:37:05 -08002024 - Encontered an array or mapp that has too many items
2025 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002026
Laurence Lundbladeee851742020-01-08 08:37:05 -08002027 - Encountered array/map nesting that is too deep
2028 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002029
Laurence Lundbladeee851742020-01-08 08:37:05 -08002030 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2031 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002032
Laurence Lundbladeee851742020-01-08 08:37:05 -08002033 - The type of a map label is not a string or int
2034 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002036 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002038 */
2039
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002040
2041
Laurence Lundbladef6531662018-12-04 10:42:22 +09002042
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002043/* ===========================================================================
2044 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002045
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002046 This implements a simple sting allocator for indefinite length
2047 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2048 implements the function type QCBORStringAllocate and allows easy
2049 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002050
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002051 This particular allocator is built-in for convenience. The caller
2052 can implement their own. All of this following code will get
2053 dead-stripped if QCBORDecode_SetMemPool() is not called.
2054
2055 This is a very primitive memory allocator. It does not track
2056 individual allocations, only a high-water mark. A free or
2057 reallocation must be of the last chunk allocated.
2058
2059 The size of the pool and offset to free memory are packed into the
2060 first 8 bytes of the memory pool so we don't have to keep them in
2061 the decode context. Since the address of the pool may not be
2062 aligned, they have to be packed and unpacked as if they were
2063 serialized data of the wire or such.
2064
2065 The sizes packed in are uint32_t to be the same on all CPU types
2066 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002067 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002068
2069
Laurence Lundbladeee851742020-01-08 08:37:05 -08002070static inline int
2071MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002072{
2073 // Use of UsefulInputBuf is overkill, but it is convenient.
2074 UsefulInputBuf UIB;
2075
Laurence Lundbladeee851742020-01-08 08:37:05 -08002076 // Just assume the size here. It was checked during SetUp so
2077 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002078 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2079 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2080 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2081 return UsefulInputBuf_GetError(&UIB);
2082}
2083
2084
Laurence Lundbladeee851742020-01-08 08:37:05 -08002085static inline int
2086MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002087{
2088 // Use of UsefulOutBuf is overkill, but convenient. The
2089 // length check performed here is useful.
2090 UsefulOutBuf UOB;
2091
2092 UsefulOutBuf_Init(&UOB, Pool);
2093 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2094 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2095 return UsefulOutBuf_GetError(&UOB);
2096}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002097
2098
2099/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002100 Internal function for an allocation, reallocation free and destuct.
2101
2102 Having only one function rather than one each per mode saves space in
2103 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002104
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002105 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2106 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002107static UsefulBuf
2108MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002109{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002110 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002111
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002112 uint32_t uPoolSize;
2113 uint32_t uFreeOffset;
2114
2115 if(uNewSize > UINT32_MAX) {
2116 // This allocator is only good up to 4GB. This check should
2117 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2118 goto Done;
2119 }
2120 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2121
2122 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2123 goto Done;
2124 }
2125
2126 if(uNewSize) {
2127 if(pMem) {
2128 // REALLOCATION MODE
2129 // Calculate pointer to the end of the memory pool. It is
2130 // assumed that pPool + uPoolSize won't wrap around by
2131 // assuming the caller won't pass a pool buffer in that is
2132 // not in legitimate memory space.
2133 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2134
2135 // Check that the pointer for reallocation is in the range of the
2136 // pool. This also makes sure that pointer math further down
2137 // doesn't wrap under or over.
2138 if(pMem >= pPool && pMem < pPoolEnd) {
2139 // Offset to start of chunk for reallocation. This won't
2140 // wrap under because of check that pMem >= pPool. Cast
2141 // is safe because the pool is always less than UINT32_MAX
2142 // because of check in QCBORDecode_SetMemPool().
2143 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2144
2145 // Check to see if the allocation will fit. uPoolSize -
2146 // uMemOffset will not wrap under because of check that
2147 // pMem is in the range of the uPoolSize by check above.
2148 if(uNewSize <= uPoolSize - uMemOffset) {
2149 ReturnValue.ptr = pMem;
2150 ReturnValue.len = uNewSize;
2151
2152 // Addition won't wrap around over because uNewSize was
2153 // checked to be sure it is less than the pool size.
2154 uFreeOffset = uMemOffset + uNewSize32;
2155 }
2156 }
2157 } else {
2158 // ALLOCATION MODE
2159 // uPoolSize - uFreeOffset will not underflow because this
2160 // pool implementation makes sure uFreeOffset is always
2161 // smaller than uPoolSize through this check here and
2162 // reallocation case.
2163 if(uNewSize <= uPoolSize - uFreeOffset) {
2164 ReturnValue.len = uNewSize;
2165 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002166 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002167 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002168 }
2169 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002170 if(pMem) {
2171 // FREE MODE
2172 // Cast is safe because of limit on pool size in
2173 // QCBORDecode_SetMemPool()
2174 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2175 } else {
2176 // DESTRUCT MODE
2177 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002178 }
2179 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002180
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002181 UsefulBuf Pool = {pPool, uPoolSize};
2182 MemPool_Pack(Pool, uFreeOffset);
2183
2184Done:
2185 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002186}
2187
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002188
Laurence Lundbladef6531662018-12-04 10:42:22 +09002189/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002190 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002191 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002192QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2193 UsefulBuf Pool,
2194 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002195{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002196 // The pool size and free mem offset are packed into the beginning
2197 // of the pool memory. This compile time check make sure the
2198 // constant in the header is correct. This check should optimize
2199 // down to nothing.
2200 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002201 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002203
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002204 // The pool size and free offset packed in to the beginning of pool
2205 // memory are only 32-bits. This check will optimize out on 32-bit
2206 // machines.
2207 if(Pool.len > UINT32_MAX) {
2208 return QCBOR_ERR_BUFFER_TOO_LARGE;
2209 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002211 // This checks that the pool buffer given is big enough.
2212 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2213 return QCBOR_ERR_BUFFER_TOO_SMALL;
2214 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002215
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002216 pMe->StringAllocator.pfAllocator = MemPool_Function;
2217 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2218 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002219
Laurence Lundblade30816f22018-11-10 13:40:22 +07002220 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002221}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002222
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002223
2224
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002225
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002226
2227
2228/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002229 Consume an entire map or array (and do next to
2230 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002231 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002232static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002233ConsumeItem(QCBORDecodeContext *pMe,
2234 const QCBORItem *pItemToConsume,
2235 uint_fast8_t *puNextNestLevel)
2236{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002237 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002238 QCBORItem Item;
2239
Laurence Lundblade02625d42020-06-25 14:41:41 -07002240 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002241
Laurence Lundblade02625d42020-06-25 14:41:41 -07002242 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002243 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002244
Laurence Lundblade1341c592020-04-11 14:19:05 -07002245 /* This works for definite and indefinite length
2246 * maps and arrays by using the nesting level
2247 */
2248 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002249 uReturn = QCBORDecode_GetNext(pMe, &Item);
2250 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002251 goto Done;
2252 }
2253 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002254
Laurence Lundblade1341c592020-04-11 14:19:05 -07002255 if(puNextNestLevel != NULL) {
2256 *puNextNestLevel = Item.uNextNestLevel;
2257 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002258 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002259
Laurence Lundblade1341c592020-04-11 14:19:05 -07002260 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002261 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002262 if(puNextNestLevel != NULL) {
2263 /* Just pass the nesting level through */
2264 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2265 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002266 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002267 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002268
2269Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002270 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002271}
2272
2273
Laurence Lundblade1341c592020-04-11 14:19:05 -07002274/* Return true if the labels in Item1 and Item2 are the same.
2275 Works only for integer and string labels. Returns false
2276 for any other type. */
2277static inline bool
2278MatchLabel(QCBORItem Item1, QCBORItem Item2)
2279{
2280 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2281 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2282 return true;
2283 }
2284 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002285 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002286 return true;
2287 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002288 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002289 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2290 return true;
2291 }
2292 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2293 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2294 return true;
2295 }
2296 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002297
Laurence Lundblade1341c592020-04-11 14:19:05 -07002298 /* Other label types are never matched */
2299 return false;
2300}
2301
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002302
2303/*
2304 Returns true if Item1 and Item2 are the same type
2305 or if either are of QCBOR_TYPE_ANY.
2306 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002307static inline bool
2308MatchType(QCBORItem Item1, QCBORItem Item2)
2309{
2310 if(Item1.uDataType == Item2.uDataType) {
2311 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002312 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002313 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002314 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002315 return true;
2316 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002317 return false;
2318}
2319
2320
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002321/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002322 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002323
2324 @param[in] pMe The decode context to search.
2325 @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002326 @param[out] puOffset Byte offset of last item matched.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002327 @param[in] pCBContext Context for the not-found item call back
2328 @param[in] pfCallback Function to call on items not matched in pItemArray
2329
2330 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2331
2332 @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.
2333
2334 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2335
2336 @retval Also errors returned by QCBORDecode_GetNext().
2337
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002338 On input pItemArray contains a list of labels and data types
2339 of items to be found.
2340
2341 On output the fully retrieved items are filled in with
2342 values and such. The label was matched, so it never changes.
2343
2344 If an item was not found, its data type is set to none.
2345
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002346 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002347static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002348MapSearch(QCBORDecodeContext *pMe,
2349 QCBORItem *pItemArray,
2350 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002351 void *pCBContext,
2352 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002353{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002354 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002355
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002356 QCBORDecodeNesting SaveNesting;
2357 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002358
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002359 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
2360 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2361 /* QCBOR_TYPE_NONE as first item indicates just looking
2362 for the end of an array, so don't give error. */
2363 uReturn = QCBOR_ERR_NOT_A_MAP;
2364 goto Done;
2365 }
2366
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002367 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002368 UsefulInputBuf_Seek(&(pMe->InBuf),
2369 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002370
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002371 /*
2372 Loop over all the items in the map. They could be
2373 deeply nested and this should handle both definite
2374 and indefinite length maps and arrays, so this
2375 adds some complexity.
2376 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002377 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002378
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002379 uint_fast8_t uNextNestLevel;
2380
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002381 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002382
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002383 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002384 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002385 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002386 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002387
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002388 /* Get the item */
2389 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390 uReturn = QCBORDecode_GetNext(pMe, &Item);
2391 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002392 /* Got non-well-formed CBOR */
2393 goto Done;
2394 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002395
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002396 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002397 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002398 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002399 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002400 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002401 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002402 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2403 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002404 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002405 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002406 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002407 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002408 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002409 goto Done;
2410 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002411
2412 /* Successful match. Return the item. */
2413 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002414 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002415 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002416 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002417 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002418 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002419 /*
2420 Call the callback on unmatched labels.
2421 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002422 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002423 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002424 */
2425 if(pfCallback) {
2426 uReturn = (*pfCallback)(pCBContext, &Item);
2427 if(uReturn != QCBOR_SUCCESS) {
2428 goto Done;
2429 }
2430 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002431 }
2432 }
2433
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002434 /*
2435 Consume the item whether matched or not. This
2436 does the work of traversing maps and array and
2437 everything in them. In this loop only the
2438 items at the current nesting level are examined
2439 to match the labels.
2440 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002441 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2442 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002443 goto Done;
2444 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002445
2446 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002447
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002448 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002449
2450 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002451 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2452 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002453
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002454 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002455 int i;
2456 QCBORItem *pIterator;
2457 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002458 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002459 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002460 }
2461 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462
2463Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002464 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002465
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002466 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002467}
2468
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002469
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002470/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002471 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002472*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002473void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2474 int64_t nLabel,
2475 uint8_t uQcborType,
2476 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002477{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002478 if(pMe->uLastError != QCBOR_SUCCESS) {
2479 return;
2480 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002481
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002482 QCBORItem OneItemSeach[2];
2483 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2484 OneItemSeach[0].label.int64 = nLabel;
2485 OneItemSeach[0].uDataType = uQcborType;
2486 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002487
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002488 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2489 if(uReturn != QCBOR_SUCCESS) {
2490 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002492 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002493 uReturn = QCBOR_ERR_NOT_FOUND;
2494 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002495 }
2496
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002497 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002498
2499 Done:
2500 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002501}
2502
2503
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002504/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002505 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002506*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002507void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2508 const char *szLabel,
2509 uint8_t uQcborType,
2510 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002511{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002512 if(pMe->uLastError != QCBOR_SUCCESS) {
2513 return;
2514 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002516 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002517 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2518 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2519 OneItemSeach[0].uDataType = uQcborType;
2520 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002521
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002522 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2523 if(uReturn != QCBOR_SUCCESS) {
2524 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002525 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002526 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002527 uReturn = QCBOR_ERR_NOT_FOUND;
2528 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002529 }
2530
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002531 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002532
2533Done:
2534 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002535}
2536
2537
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002538/**
2539 @param[in] TagSpec Specification for matching tags.
2540 @param[in] uDataType A QCBOR data type
2541
2542 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2543 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2544
2545 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2546 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002547static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002548{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002549 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2550 /* Must match the tag */
2551 if(uDataType == TagSpec.uTaggedType) {
2552 return QCBOR_SUCCESS;
2553 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002554 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002555 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2556 /* Must check all the possible types for the tag content */
2557 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002558 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2559 return QCBOR_SUCCESS;
2560 }
2561 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002562 /* Didn't match any of the tag content types */
2563 /* Check the tag for the either case */
2564 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2565 if(uDataType == TagSpec.uTaggedType) {
2566 return QCBOR_SUCCESS;
2567 }
2568 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002569 }
2570
2571 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002572}
2573
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002574
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002575// Semi-private
2576// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002577void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2578 int64_t nLabel,
2579 TagSpecification TagSpec,
2580 QCBORItem *pItem)
2581{
2582 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2583 if(pMe->uLastError != QCBOR_SUCCESS) {
2584 return;
2585 }
2586
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002587 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002588}
2589
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002590// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002591void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2592 const char *szLabel,
2593 TagSpecification TagSpec,
2594 QCBORItem *pItem)
2595{
2596 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2597 if(pMe->uLastError != QCBOR_SUCCESS) {
2598 return;
2599 }
2600
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002601 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002602}
2603
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002604// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002605void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2606 int64_t nLabel,
2607 TagSpecification TagSpec,
2608 UsefulBufC *pString)
2609{
2610 QCBORItem Item;
2611 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2612 if(pMe->uLastError == QCBOR_SUCCESS) {
2613 *pString = Item.val.string;
2614 }
2615}
2616
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002617// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002618void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2619 const char * szLabel,
2620 TagSpecification TagSpec,
2621 UsefulBufC *pString)
2622{
2623 QCBORItem Item;
2624 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2625 if(pMe->uLastError == QCBOR_SUCCESS) {
2626 *pString = Item.val.string;
2627 }
2628}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002629
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002630/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002631 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002632*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002633QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2634{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002635 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002636}
2637
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002638/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002639 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002640*/
2641QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2642 QCBORItem *pItemList,
2643 void *pCallbackCtx,
2644 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002645{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002646 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002647}
2648
2649
Laurence Lundblade34691b92020-05-18 22:25:25 -07002650static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002651{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002652 if(pMe->uLastError != QCBOR_SUCCESS) {
2653 // Already in error state; do nothing.
2654 return;
2655 }
2656
2657 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002658 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002659 if(pMe->uLastError != QCBOR_SUCCESS) {
2660 return;
2661 }
2662
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002663 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002664 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002665
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002666 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002667 be at the right place.
2668
2669 The UsefulInBuf offset could be anywhere, so no assumption is
2670 made about it.
2671
2672 No assumption is made about the pre-order nesting level either.
2673
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002674 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002675 the map level that is being entered.
2676 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002677 /* Seek to the data item that is the map or array */
2678 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002679
2680 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002681
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002682 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002683}
2684
2685
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002686/*
2687Public function, see header qcbor/qcbor_decode.h file
2688*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002689void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002690{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002691 QCBORItem OneItemSeach[2];
2692 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2693 OneItemSeach[0].label.int64 = nLabel;
2694 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2695 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002696
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002697 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002698 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002699}
2700
2701
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002702/*
2703Public function, see header qcbor/qcbor_decode.h file
2704*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002705void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002706{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002707 QCBORItem OneItemSeach[2];
2708 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2709 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2710 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2711 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002712
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002713 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002714}
2715
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002716/*
2717Public function, see header qcbor/qcbor_decode.h file
2718*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002719void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002720{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002721 QCBORItem OneItemSeach[2];
2722 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2723 OneItemSeach[0].label.int64 = nLabel;
2724 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2725 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002726
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002727 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002728}
2729
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730/*
2731Public function, see header qcbor/qcbor_decode.h file
2732*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002733void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2734{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002735 QCBORItem OneItemSeach[2];
2736 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2737 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2738 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2739 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002740
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002741 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002742}
2743
2744
Laurence Lundblade02625d42020-06-25 14:41:41 -07002745// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002746void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002748 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002749 if(pMe->uLastError != QCBOR_SUCCESS) {
2750 // Already in error state; do nothing.
2751 return;
2752 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002753
2754 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002755 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002756 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002757 if(pMe->uLastError != QCBOR_SUCCESS) {
2758 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002759 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002760 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002761 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2762 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002763 }
2764
Laurence Lundblade02625d42020-06-25 14:41:41 -07002765 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002766
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002767 QCBORError uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting),
2768 UsefulInputBuf_Tell(&(pMe->InBuf)));
2769
2770 pMe->uLastError = (uint8_t)uErr;
2771
Laurence Lundblade02625d42020-06-25 14:41:41 -07002772 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773}
2774
Laurence Lundblade02625d42020-06-25 14:41:41 -07002775
2776/*
2777 This is for exiting a level that is a bounded map, array or bstr
2778 wrapped CBOR. It is the work common to these.
2779
2780 One chunk of work is to set up the pre-order traversal so it is at
2781 the item just after the bounded map, array or bstr that is being
2782 exited. This is somewhat complex.
2783
2784 The other work is to level-up the bounded mode to next higest bounded
2785 mode or the top level if there isn't one.
2786 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002787static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002788ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002789{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002790 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002791
Laurence Lundblade02625d42020-06-25 14:41:41 -07002792 /*
2793 First the pre-order-traversal byte offset is positioned to the
2794 item just after the bounded mode item that was just consumed.
2795 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002796 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2797
Laurence Lundblade02625d42020-06-25 14:41:41 -07002798 /*
2799 Next, set the current nesting level to one above the bounded level
2800 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002801
Laurence Lundblade02625d42020-06-25 14:41:41 -07002802 DecodeNesting_CheckBoundedType() is always called before this and
2803 makes sure pCurrentBounded is valid.
2804 */
2805 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2806
2807 /*
2808 This does the complex work of leveling up the pre-order traversal
2809 when the end of a map or array or another bounded level is
2810 reached. It may do nothing, or ascend all the way to the top
2811 level.
2812 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002813 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002814 if(uErr != QCBOR_SUCCESS) {
2815 goto Done;
2816 }
2817
Laurence Lundblade02625d42020-06-25 14:41:41 -07002818 /*
2819 This makes the next highest bounded level the current bounded
2820 level. If there is no next highest level, then no bounded mode is
2821 in effect.
2822 */
2823 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002824
Laurence Lundblade02625d42020-06-25 14:41:41 -07002825 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002826
2827Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002828 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002829 return uErr;
2830}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002831
Laurence Lundblade02625d42020-06-25 14:41:41 -07002832
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002833// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002834void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002835{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002836 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002837 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002838 return;
2839 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002840
Laurence Lundblade02625d42020-06-25 14:41:41 -07002841 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002842
Laurence Lundblade02625d42020-06-25 14:41:41 -07002843 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002844 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2845 goto Done;
2846 }
2847
Laurence Lundblade02625d42020-06-25 14:41:41 -07002848 /*
2849 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002850 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002851 from previous map search, then do a dummy search.
2852 */
2853 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002854 QCBORItem Dummy;
2855 Dummy.uLabelType = QCBOR_TYPE_NONE;
2856 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2857 if(uErr != QCBOR_SUCCESS) {
2858 goto Done;
2859 }
2860 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002861
Laurence Lundblade02625d42020-06-25 14:41:41 -07002862 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002863
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002864Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002865 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002866}
2867
2868
Laurence Lundblade1341c592020-04-11 14:19:05 -07002869void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002870{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002871 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002872 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2873 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002874}
2875
2876
Laurence Lundblade1341c592020-04-11 14:19:05 -07002877
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002878static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002879 const QCBORItem *pItem,
2880 uint8_t uTagRequirement,
2881 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002882{
2883 if(pMe->uLastError != QCBOR_SUCCESS) {
2884 // Already in error state; do nothing.
2885 return pMe->uLastError;
2886 }
2887
2888 QCBORError uError = QCBOR_SUCCESS;
2889
2890 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2891 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2892 goto Done;;
2893 }
2894
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002895 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002896 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2897
2898 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2899 if(uError != QCBOR_SUCCESS) {
2900 goto Done;
2901 }
2902
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002903 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002904 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002905 so the increment in NestLevelAscender called by ExitBoundedLevel()
2906 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002907 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002908 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002909
2910 if(pBstr) {
2911 *pBstr = pItem->val.string;
2912 }
2913
2914 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002915
2916 // Need to move UIB input cursor to the right place
2917
2918 // Really this is a subtraction and an assignment; not much code
2919 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002920 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002921
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002922 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002923
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002924 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2925
2926 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002927
Laurence Lundblade02625d42020-06-25 14:41:41 -07002928 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2929 uPreviousLength,
2930 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002931Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002932 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002933
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002934 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002935}
2936
2937
Laurence Lundblade02625d42020-06-25 14:41:41 -07002938/*
2939 Public function, see header qcbor/qcbor_decode.h file
2940 */
2941void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002942 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002943 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002944{
2945 if(pMe->uLastError != QCBOR_SUCCESS) {
2946 // Already in error state; do nothing.
2947 return;
2948 }
2949
2950 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002951 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002952 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2953 if(pMe->uLastError != QCBOR_SUCCESS) {
2954 return;
2955 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002956
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002957 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002958 &Item,
2959 uTagRequirement,
2960 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002961}
2962
2963
Laurence Lundblade02625d42020-06-25 14:41:41 -07002964/*
2965 Public function, see header qcbor/qcbor_decode.h file
2966 */
2967void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2968 uint8_t uTagRequirement,
2969 int64_t nLabel,
2970 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002971{
2972 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002973 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002974
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002975 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002976}
2977
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002978
Laurence Lundblade02625d42020-06-25 14:41:41 -07002979/*
2980 Public function, see header qcbor/qcbor_decode.h file
2981 */
2982void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
2983 uint8_t uTagRequirement,
2984 const char *szLabel,
2985 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002986{
2987 QCBORItem Item;
2988 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2989
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002990 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002991}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002992
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002993
Laurence Lundblade02625d42020-06-25 14:41:41 -07002994/*
2995 Public function, see header qcbor/qcbor_decode.h file
2996 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002997void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002998{
Laurence Lundblade02625d42020-06-25 14:41:41 -07002999 if(pMe->uLastError != QCBOR_SUCCESS) {
3000 // Already in error state; do nothing.
3001 return;
3002 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003003
Laurence Lundblade02625d42020-06-25 14:41:41 -07003004 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3005 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3006 return;
3007 }
3008
3009 /*
3010 Reset the length of the UsefulInputBuf to what it was before
3011 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003012 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003013 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3014 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003015
3016
Laurence Lundblade02625d42020-06-25 14:41:41 -07003017 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003018 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003019}
3020
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003021
Laurence Lundbladee6430642020-03-14 21:15:44 -07003022
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003023
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003024
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003025
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003026
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003027
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003028static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3029{
3030 switch(pItem->uDataType) {
3031 case QCBOR_TYPE_TRUE:
3032 *pBool = true;
3033 return QCBOR_SUCCESS;
3034 break;
3035
3036 case QCBOR_TYPE_FALSE:
3037 *pBool = false;
3038 return QCBOR_SUCCESS;
3039 break;
3040
3041 default:
3042 return QCBOR_ERR_UNEXPECTED_TYPE;
3043 break;
3044 }
3045}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003046
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003047/*
3048Public function, see header qcbor/qcbor_decode.h file
3049*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003050void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003051{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003052 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003053 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003054 return;
3055 }
3056
Laurence Lundbladec4537442020-04-14 18:53:22 -07003057 QCBORError nError;
3058 QCBORItem Item;
3059
3060 nError = QCBORDecode_GetNext(pMe, &Item);
3061 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003062 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003063 return;
3064 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003065 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003066}
3067
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003068/*
3069Public function, see header qcbor/qcbor_decode.h file
3070*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003071void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003072{
3073 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003074 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003075
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003076 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003077}
3078
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003079/*
3080Public function, see header qcbor/qcbor_decode.h file
3081*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003082void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3083{
3084 QCBORItem Item;
3085 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3086
3087 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3088}
3089
3090
3091
3092void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003093{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003094 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003095 // Already in error state, do nothing
3096 return;
3097 }
3098
3099 QCBORError nError;
3100 QCBORItem Item;
3101
3102 nError = QCBORDecode_GetNext(pMe, &Item);
3103 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003104 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003105 return;
3106 }
3107
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003108 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3109
3110 if(pMe->uLastError == QCBOR_SUCCESS) {
3111 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003112 }
3113}
3114
Laurence Lundbladec4537442020-04-14 18:53:22 -07003115
3116
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003117
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003118static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003119{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003120 *pbIsNegative = false;
3121
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003122 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 -07003123
3124 switch(pItem->uDataType) {
3125 case QCBOR_TYPE_BYTE_STRING:
3126 // TODO: check that there is no tag here?
3127 if(bMustBeTagged) {
3128 return QCBOR_ERR_UNEXPECTED_TYPE;
3129 } else {
3130 *pValue = pItem->val.string;
3131 return QCBOR_SUCCESS;
3132 }
3133 break;
3134
3135 case QCBOR_TYPE_POSBIGNUM:
3136 *pValue = pItem->val.string;
3137 return QCBOR_SUCCESS;
3138 break;
3139
3140 case QCBOR_TYPE_NEGBIGNUM:
3141 *pbIsNegative = true;
3142 *pValue = pItem->val.string;
3143 return QCBOR_SUCCESS;
3144 break;
3145
3146 default:
3147 return QCBOR_ERR_UNEXPECTED_TYPE;
3148 break;
3149 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003150}
3151
3152
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003153/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003154 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3155 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3156 will always be false on the asumption that it is positive, but it can be interpretted as
3157 negative if the the sign is know from other context.
3158 @param[out] pValue The bytes that make up the big num
3159 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3160
3161 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3162 a positive big num or a negative big num.
3163
3164 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003165void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003166{
3167 if(pMe->uLastError != QCBOR_SUCCESS) {
3168 // Already in error state, do nothing
3169 return;
3170 }
3171
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003172 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003173 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3174 if(uError != QCBOR_SUCCESS) {
3175 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003176 return;
3177 }
3178
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003179 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003180}
3181
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003182/*
3183Public function, see header qcbor/qcbor_decode.h file
3184*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003185void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003186{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003187 QCBORItem Item;
3188 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003189
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003190 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003191}
3192
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003193/*
3194Public function, see header qcbor/qcbor_decode.h file
3195*/
3196void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3197{
3198 QCBORItem Item;
3199 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3200
3201 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3202}
3203
3204
3205
3206// Semi private
3207QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3208{
3209 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3210 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3211
3212 QCBORError uReturn;
3213
3214 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3215 *pMessage = pItem->val.string;
3216 if(pbIsNot7Bit != NULL) {
3217 *pbIsNot7Bit = false;
3218 }
3219 uReturn = QCBOR_SUCCESS;
3220 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3221 *pMessage = pItem->val.string;
3222 if(pbIsNot7Bit != NULL) {
3223 *pbIsNot7Bit = true;
3224 }
3225 uReturn = QCBOR_SUCCESS;
3226
3227 } else {
3228 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3229 }
3230
3231 return uReturn;
3232}
3233
3234
3235
3236
3237
Laurence Lundbladec4537442020-04-14 18:53:22 -07003238
3239
3240
Laurence Lundbladee6430642020-03-14 21:15:44 -07003241
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003242typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003243
3244
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003245// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003246static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003247{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003248 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003249
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003250 if(uResult != 0) {
3251 /* This loop will run a maximum of 19 times because
3252 * UINT64_MAX < 10 ^^ 19. More than that will cause
3253 * exit with the overflow error
3254 */
3255 for(; nExponent > 0; nExponent--) {
3256 if(uResult > UINT64_MAX / 10) {
3257 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3258 }
3259 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003260 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003262 for(; nExponent < 0; nExponent++) {
3263 uResult = uResult / 10;
3264 if(uResult == 0) {
3265 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3266 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003267 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003268 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003269 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003270
3271 *puResult = uResult;
3272
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003273 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003274}
3275
3276
Laurence Lundbladee6430642020-03-14 21:15:44 -07003277/* Convert a decimal fraction to an int64_t without using
3278 floating point or math libraries. Most decimal fractions
3279 will not fit in an int64_t and this will error out with
3280 under or overflow
3281 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003282static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003283{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003284 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003285
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003286 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003287
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003288 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003289 * INT64_MAX < 2^31. More than that will cause
3290 * exist with the overflow error
3291 */
3292 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003293 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003294 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003295 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003296 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003297 nExponent--;
3298 }
3299
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003300 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003301 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003302 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3303 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003304 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003305 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003306 }
3307
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003308 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003309
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003310 return QCBOR_SUCCESS;
3311}
3312
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003313/*
3314 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3315 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003316static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3317{
3318 uint64_t uResult;
3319
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003320 // Take the absolute value of the mantissa and convert to unsigned.
3321 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003322 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3323
3324 // Do the exponentiation of the positive mantissa
3325 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3326 if(uReturn) {
3327 return uReturn;
3328 }
3329
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003330
Laurence Lundblade983500d2020-05-14 11:49:34 -07003331 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3332 of INT64_MIN. This assumes two's compliment representation where
3333 INT64_MIN is one increment farther from 0 than INT64_MAX.
3334 Trying to write -INT64_MIN doesn't work to get this because the
3335 compiler tries to work with an int64_t which can't represent
3336 -INT64_MIN.
3337 */
3338 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3339
3340 // Error out if too large
3341 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003342 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3343 }
3344
3345 // Casts are safe because of checks above
3346 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3347
3348 return QCBOR_SUCCESS;
3349}
3350
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003351/*
3352 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3353 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003354static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3355{
3356 if(nMantissa < 0) {
3357 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3358 }
3359
3360 // Cast to unsigned is OK because of check for negative
3361 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3362 // Exponentiation is straight forward
3363 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3364}
3365
3366
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003367#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003368
3369
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003370static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003371{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003373
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003374 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003375 const uint8_t *pByte = BigNum.ptr;
3376 size_t uLen = BigNum.len;
3377 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003378 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003379 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003380 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003381 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003382 }
3383
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003384 *pResult = uResult;
3385 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386}
3387
Laurence Lundblade887add82020-05-17 05:50:34 -07003388static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003389{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003390 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003391}
3392
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003393static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394{
3395 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003396 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3397 if(uError) {
3398 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003399 }
3400 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3401 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003402 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003403}
3404
3405
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003406static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003407{
3408 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003409 /* negaative int furthest from zero is INT64_MIN
3410 which is expressed as -INT64_MAX-1. The value of
3411 a negative bignum is -n-1, one further from zero
3412 than the positive bignum */
3413
3414 /* say INT64_MIN is -2; then INT64_MAX is 1.
3415 Then -n-1 <= INT64_MIN.
3416 Then -n -1 <= -INT64_MAX - 1
3417 THen n <= INT64_MAX. */
3418 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003419 if(uError) {
3420 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003421 }
3422 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003423 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003424 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003425 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003426 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003427}
3428
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003429#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003430
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003431
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003432/*
3433Convert a integers and floats to an int64_t.
3434
3435\param[in] uOptions Bit mask list of conversion options.
3436
3437\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3438
3439\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3440
3441\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3442
3443*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003444static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3445{
3446 switch(pItem->uDataType) {
3447 // TODO: float when ifdefs are set
3448 case QCBOR_TYPE_DOUBLE:
3449 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3450 // TODO: what about under/overflow here?
3451 // Invokes the floating-point HW and/or compiler-added libraries
3452 feclearexcept(FE_ALL_EXCEPT);
3453 *pnValue = llround(pItem->val.dfnum);
3454 if(fetestexcept(FE_INVALID)) {
3455 // TODO: better error code
3456 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3457 }
3458 } else {
3459 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3460 }
3461 break;
3462
3463 case QCBOR_TYPE_INT64:
3464 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3465 *pnValue = pItem->val.int64;
3466 } else {
3467 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3468 }
3469 break;
3470
3471 case QCBOR_TYPE_UINT64:
3472 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3473 if(pItem->val.uint64 < INT64_MAX) {
3474 *pnValue = pItem->val.int64;
3475 } else {
3476 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3477 }
3478 } else {
3479 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3480 }
3481 break;
3482
3483 default:
3484 return QCBOR_ERR_UNEXPECTED_TYPE;
3485 }
3486 return QCBOR_SUCCESS;
3487}
3488
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003489
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003490void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3491 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003492 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003493 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003494{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003495 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003496 return;
3497 }
3498
Laurence Lundbladee6430642020-03-14 21:15:44 -07003499 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003500 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3501 if(uError) {
3502 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003503 return;
3504 }
3505
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003506 if(pItem) {
3507 *pItem = Item;
3508 }
3509
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003510 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003511}
3512
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003513
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003514void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3515 int64_t nLabel,
3516 uint32_t uOptions,
3517 int64_t *pnValue,
3518 QCBORItem *pItem)
3519{
3520 QCBORItem Item;
3521 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003522 if(pMe->uLastError != QCBOR_SUCCESS) {
3523 return;
3524 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003525
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003526 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003527}
3528
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003529
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003530void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3531 const char * szLabel,
3532 uint32_t uOptions,
3533 int64_t *pnValue,
3534 QCBORItem *pItem)
3535{
3536 if(pMe->uLastError != QCBOR_SUCCESS) {
3537 return;
3538 }
3539
3540 QCBORItem Item;
3541 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003542 if(pMe->uLastError != QCBOR_SUCCESS) {
3543 return;
3544 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003545
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003546 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003547}
3548
3549
3550
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003551/*
3552 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003553
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003554 \param[in] uOptions Bit mask list of conversion options.
3555
3556 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3557
3558 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3559
3560 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3561
3562 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003563static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3564{
3565 QCBORError uErr;
3566
3567 switch(pItem->uDataType) {
3568
3569 case QCBOR_TYPE_POSBIGNUM:
3570 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3571 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003572 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003574 }
3575 break;
3576
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003577 case QCBOR_TYPE_NEGBIGNUM:
3578 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3579 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003580 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003581 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003582 }
3583 break;
3584
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003585#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3586 case QCBOR_TYPE_DECIMAL_FRACTION:
3587 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3588 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3589 pItem->val.expAndMantissa.nExponent,
3590 pnValue,
3591 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003592 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3594 }
3595 break;
3596
3597 case QCBOR_TYPE_BIGFLOAT:
3598 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3599 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3600 pItem->val.expAndMantissa.nExponent,
3601 pnValue,
3602 Exponentitate2);
3603 } else {
3604 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3605 }
3606 break;
3607
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003608 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3609 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3610 int64_t nMantissa;
3611 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3612 if(uErr) {
3613 return uErr;
3614 }
3615 return ExponentiateNN(nMantissa,
3616 pItem->val.expAndMantissa.nExponent,
3617 pnValue,
3618 Exponentitate10);
3619 } else {
3620 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3621 }
3622 break;
3623
3624 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3625 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3626 int64_t nMantissa;
3627 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3628 if(uErr) {
3629 return uErr;
3630 }
3631 return ExponentiateNN(nMantissa,
3632 pItem->val.expAndMantissa.nExponent,
3633 pnValue,
3634 Exponentitate10);
3635 } else {
3636 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3637 }
3638 break;
3639
3640 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3641 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3642 int64_t nMantissa;
3643 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3644 if(uErr) {
3645 return uErr;
3646 }
3647 return ExponentiateNN(nMantissa,
3648 pItem->val.expAndMantissa.nExponent,
3649 pnValue,
3650 Exponentitate2);
3651 } else {
3652 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3653 }
3654 break;
3655
3656 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3657 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3658 int64_t nMantissa;
3659 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3660 if(uErr) {
3661 return uErr;
3662 }
3663 return ExponentiateNN(nMantissa,
3664 pItem->val.expAndMantissa.nExponent,
3665 pnValue,
3666 Exponentitate2);
3667 } else {
3668 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003669 }
3670 break;
3671
Laurence Lundbladec4537442020-04-14 18:53:22 -07003672 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003673 return QCBOR_ERR_UNEXPECTED_TYPE;
3674#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003675 }
3676}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003677
3678
Laurence Lundbladec4537442020-04-14 18:53:22 -07003679/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003680 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003681 */
3682void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003683{
3684 QCBORItem Item;
3685
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003686 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003687
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003688 if(pMe->uLastError == QCBOR_SUCCESS) {
3689 // The above conversion succeeded
3690 return;
3691 }
3692
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003693 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003694 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003695 return;
3696 }
3697
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003698 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003699}
3700
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003701
3702/*
3703Public function, see header qcbor/qcbor_decode.h file
3704*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003705void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3706{
3707 QCBORItem Item;
3708
3709 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3710
3711 if(pMe->uLastError == QCBOR_SUCCESS) {
3712 // The above conversion succeeded
3713 return;
3714 }
3715
3716 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3717 // The above conversion failed in a way that code below can't correct
3718 return;
3719 }
3720
3721 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3722}
3723
3724
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003725/*
3726Public function, see header qcbor/qcbor_decode.h file
3727*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003728void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3729{
3730 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003731 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3732
3733 if(pMe->uLastError == QCBOR_SUCCESS) {
3734 // The above conversion succeeded
3735 return;
3736 }
3737
3738 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3739 // The above conversion failed in a way that code below can't correct
3740 return;
3741 }
3742
3743 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3744}
3745
3746
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003747static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3748{
3749 switch(pItem->uDataType) {
3750 // TODO: type flaot
3751 case QCBOR_TYPE_DOUBLE:
3752 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3753 feclearexcept(FE_ALL_EXCEPT);
3754 double dRounded = round(pItem->val.dfnum);
3755 // TODO: over/underflow
3756 if(fetestexcept(FE_INVALID)) {
3757 // TODO: better error code
3758 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3759 } else if(isnan(dRounded)) {
3760 // TODO: better error code
3761 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3762 } else if(dRounded >= 0) {
3763 *puValue = (uint64_t)dRounded;
3764 } else {
3765 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3766 }
3767 } else {
3768 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3769 }
3770 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003771
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003772 case QCBOR_TYPE_INT64:
3773 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3774 if(pItem->val.int64 >= 0) {
3775 *puValue = (uint64_t)pItem->val.int64;
3776 } else {
3777 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3778 }
3779 } else {
3780 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3781 }
3782 break;
3783
3784 case QCBOR_TYPE_UINT64:
3785 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3786 *puValue = pItem->val.uint64;
3787 } else {
3788 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3789 }
3790 break;
3791
3792 default:
3793 return QCBOR_ERR_UNEXPECTED_TYPE;
3794 }
3795 return QCBOR_SUCCESS;
3796}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003797
3798
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003799void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3800 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003801 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003802 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003803{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804 if(pMe->uLastError != QCBOR_SUCCESS) {
3805 return;
3806 }
3807
Laurence Lundbladec4537442020-04-14 18:53:22 -07003808 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003809
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003810 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3811 if(uError) {
3812 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003813 return;
3814 }
3815
Laurence Lundbladea826c502020-05-10 21:07:00 -07003816 if(pItem) {
3817 *pItem = Item;
3818 }
3819
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003820 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003821}
3822
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003823
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003824void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3825{
3826 int64_t uValue;
3827 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3828 if(pMe->uLastError != QCBOR_SUCCESS) {
3829 return;
3830 }
3831
3832 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3833 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3834 }
3835}
3836
3837void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3838{
3839 int64_t uValue;
3840 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3841 if(pMe->uLastError != QCBOR_SUCCESS) {
3842 return;
3843 }
3844
3845 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3846 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3847 }
3848}
3849
3850void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3851{
3852 int64_t uValue;
3853 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3854 if(pMe->uLastError != QCBOR_SUCCESS) {
3855 return;
3856 }
3857
3858 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3859 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3860 }
3861}
3862
3863
3864
3865
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003866void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3867 int64_t nLabel,
3868 uint32_t uOptions,
3869 uint64_t *puValue,
3870 QCBORItem *pItem)
3871{
3872 QCBORItem Item;
3873 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003874 if(pMe->uLastError != QCBOR_SUCCESS) {
3875 return;
3876 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003877
3878 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3879}
3880
3881
3882void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3883 const char * szLabel,
3884 uint32_t uOptions,
3885 uint64_t *puValue,
3886 QCBORItem *pItem)
3887{
3888 if(pMe->uLastError != QCBOR_SUCCESS) {
3889 return;
3890 }
3891
3892 QCBORItem Item;
3893 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003894 if(pMe->uLastError != QCBOR_SUCCESS) {
3895 return;
3896 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003897
3898 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3899}
3900
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003901/*
3902 Public function, see header qcbor/qcbor_decode.h file
3903*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003904static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3905{
3906 QCBORError uErr;
3907
3908 switch(pItem->uDataType) {
3909
3910 case QCBOR_TYPE_POSBIGNUM:
3911 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3912 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3913 } else {
3914 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3915 }
3916 break;
3917
3918 case QCBOR_TYPE_NEGBIGNUM:
3919 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3920 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3921 } else {
3922 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3923 }
3924 break;
3925
3926#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3927
3928 case QCBOR_TYPE_DECIMAL_FRACTION:
3929 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3930 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3931 pItem->val.expAndMantissa.nExponent,
3932 puValue,
3933 Exponentitate10);
3934 } else {
3935 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3936 }
3937 break;
3938
3939 case QCBOR_TYPE_BIGFLOAT:
3940 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3941 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3942 pItem->val.expAndMantissa.nExponent,
3943 puValue,
3944 Exponentitate2);
3945 } else {
3946 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3947 }
3948 break;
3949
3950 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3951 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3952 // TODO: Would be better to convert to unsigned
3953 int64_t nMantissa;
3954 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3955 if(uErr != QCBOR_SUCCESS) {
3956 return uErr;
3957 }
3958 return ExponentitateNU(nMantissa,
3959 pItem->val.expAndMantissa.nExponent,
3960 puValue,
3961 Exponentitate10);
3962 } else {
3963 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3964 }
3965 break;
3966
3967 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3968 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3969 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3970 } else {
3971 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3972 }
3973 break;
3974
3975 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3976 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3977 // TODO: Would be better to convert to unsigned
3978 int64_t nMantissa;
3979 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3980 if(uErr != QCBOR_SUCCESS) {
3981 return uErr;
3982 }
3983 return ExponentitateNU(nMantissa,
3984 pItem->val.expAndMantissa.nExponent,
3985 puValue,
3986 Exponentitate2);
3987 } else {
3988 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3989 }
3990 break;
3991
3992 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3993 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3994 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3995 } else {
3996 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3997 }
3998 break;
3999#endif
4000 default:
4001 return QCBOR_ERR_UNEXPECTED_TYPE;
4002 }
4003}
4004
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004005/*
4006 Public function, see header qcbor/qcbor_decode.h file
4007*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004008void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004009{
4010 QCBORItem Item;
4011
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004012 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004013
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004014 if(pMe->uLastError == QCBOR_SUCCESS) {
4015 // The above conversion succeeded
4016 return;
4017 }
4018
4019 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4020 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004021 return;
4022 }
4023
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004024 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004025}
4026
Laurence Lundbladec4537442020-04-14 18:53:22 -07004027
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004028/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004029 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004030*/
4031void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4032{
4033 QCBORItem Item;
4034
4035 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4036
4037 if(pMe->uLastError == QCBOR_SUCCESS) {
4038 // The above conversion succeeded
4039 return;
4040 }
4041
4042 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4043 // The above conversion failed in a way that code below can't correct
4044 return;
4045 }
4046
4047 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4048}
4049
4050
4051/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004052 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004053*/
4054void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4055{
4056 QCBORItem Item;
4057 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4058
4059 if(pMe->uLastError == QCBOR_SUCCESS) {
4060 // The above conversion succeeded
4061 return;
4062 }
4063
4064 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4065 // The above conversion failed in a way that code below can't correct
4066 return;
4067 }
4068
4069 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4070}
4071
4072
4073static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4074{
4075 switch(pItem->uDataType) {
4076 // TODO: float when ifdefs are set
4077 case QCBOR_TYPE_DOUBLE:
4078 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4079 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4080 *pdValue = pItem->val.dfnum;
4081 } else {
4082 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4083 }
4084 }
4085 break;
4086
4087 case QCBOR_TYPE_INT64:
4088 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4089 // TODO: how does this work?
4090 *pdValue = (double)pItem->val.int64;
4091
4092 } else {
4093 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4094 }
4095 break;
4096
4097 case QCBOR_TYPE_UINT64:
4098 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4099 *pdValue = (double)pItem->val.uint64;
4100 } else {
4101 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4102 }
4103 break;
4104
4105 default:
4106 return QCBOR_ERR_UNEXPECTED_TYPE;
4107 }
4108
4109 return QCBOR_SUCCESS;
4110}
4111
4112
4113
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004114void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4115 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004116 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004117 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004118{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004119 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004120 return;
4121 }
4122
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004123 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004124
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004125 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004126 if(uError) {
4127 pMe->uLastError = (uint8_t)uError;
4128 return;
4129 }
4130
4131 if(pItem) {
4132 *pItem = Item;
4133 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004134
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004135 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004136}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004137
Laurence Lundbladec4537442020-04-14 18:53:22 -07004138
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004139void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4140 int64_t nLabel,
4141 uint32_t uOptions,
4142 double *pdValue,
4143 QCBORItem *pItem)
4144{
4145 QCBORItem Item;
4146 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004147 if(pMe->uLastError != QCBOR_SUCCESS) {
4148 return;
4149 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004150
4151 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4152}
4153
4154void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4155 const char * szLabel,
4156 uint32_t uOptions,
4157 double *pdValue,
4158 QCBORItem *pItem)
4159{
4160 if(pMe->uLastError != QCBOR_SUCCESS) {
4161 return;
4162 }
4163
4164 QCBORItem Item;
4165 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004166 if(pMe->uLastError != QCBOR_SUCCESS) {
4167 return;
4168 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004169
4170 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4171}
4172
4173
4174
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004175static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4176{
4177 double dResult;
4178
4179 dResult = 0.0;
4180 const uint8_t *pByte = BigNum.ptr;
4181 size_t uLen = BigNum.len;
4182 /* This will overflow and become the float value INFINITY if the number
4183 is too large to fit. No error will be logged.
4184 TODO: should an error be logged? */
4185 while(uLen--) {
4186 dResult = (dResult * 256.0) + (double)*pByte++;
4187 }
4188
4189 return dResult;
4190}
4191
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004192static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004193{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004194 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004195 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4196
4197 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004198 switch(pItem->uDataType) {
4199 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004200
4201#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004202 case QCBOR_TYPE_DECIMAL_FRACTION:
4203 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4204 // TODO: rounding and overflow errors
4205 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4206 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4207 } else {
4208 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4209 }
4210 break;
4211
4212 case QCBOR_TYPE_BIGFLOAT:
4213 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4214 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4215 exp2((double)pItem->val.expAndMantissa.nExponent);
4216 } else {
4217 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4218 }
4219 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004220#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221
4222 case QCBOR_TYPE_POSBIGNUM:
4223 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4224 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4225 } else {
4226 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4227 }
4228 break;
4229
4230 case QCBOR_TYPE_NEGBIGNUM:
4231 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004232 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233 } else {
4234 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4235 }
4236 break;
4237
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004238#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004239 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4240 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4241 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4242 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4243 } else {
4244 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4245 }
4246 break;
4247
4248 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4249 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4250 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4251 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4252 } else {
4253 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4254 }
4255 break;
4256
4257 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4258 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4259 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4260 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4261 } else {
4262 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4263 }
4264 break;
4265
4266 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4267 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004268 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004269 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4270 } else {
4271 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4272 }
4273 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004274#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4275
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004276
4277 default:
4278 return QCBOR_ERR_UNEXPECTED_TYPE;
4279 }
4280
4281 return QCBOR_SUCCESS;
4282}
4283
4284
4285/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004286 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004287*/
4288void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4289{
4290
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004291 QCBORItem Item;
4292
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004293 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004294
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
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004305 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004306}
4307
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004308
4309/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004310 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004311*/
4312void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4313{
4314 QCBORItem Item;
4315
4316 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4317
4318 if(pMe->uLastError == QCBOR_SUCCESS) {
4319 // The above conversion succeeded
4320 return;
4321 }
4322
4323 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4324 // The above conversion failed in a way that code below can't correct
4325 return;
4326 }
4327
4328 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4329}
4330
4331
4332/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004333 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004334*/
4335void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4336{
4337 QCBORItem Item;
4338 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4339
4340 if(pMe->uLastError == QCBOR_SUCCESS) {
4341 // The above conversion succeeded
4342 return;
4343 }
4344
4345 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4346 // The above conversion failed in a way that code below can't correct
4347 return;
4348 }
4349
4350 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4351}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004352
4353
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004354#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004355void FarfDecimalFraction(QCBORDecodeContext *pMe,
4356 uint8_t uTagRequirement,
4357 QCBORItem *pItem,
4358 int64_t *pnMantissa,
4359 int64_t *pnExponent)
4360{
4361 QCBORError uErr;
4362
4363 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4364 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4365 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4366 return;
4367 }
4368 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4369 if(uErr != QCBOR_SUCCESS) {
4370 pMe->uLastError = (uint8_t)uErr;
4371 return;
4372 }
4373 }
4374
4375 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4376 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4377 return;
4378 }
4379
4380 switch (pItem->uDataType) {
4381
4382 case QCBOR_TYPE_DECIMAL_FRACTION:
4383 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4384 *pnExponent = pItem->val.expAndMantissa.nExponent;
4385 break;
4386
4387 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4388 *pnExponent = pItem->val.expAndMantissa.nExponent;
4389
4390 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4391 if(uErr != QCBOR_SUCCESS) {
4392 pMe->uLastError = (uint8_t)uErr;
4393 }
4394 break;
4395
4396 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4397 *pnExponent = pItem->val.expAndMantissa.nExponent;
4398
4399 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4400 if(uErr != QCBOR_SUCCESS) {
4401 pMe->uLastError = (uint8_t)uErr;
4402 }
4403 break;
4404
4405 default:
4406 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4407 }
4408}
4409
4410void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4411 uint8_t uTagRequirement,
4412 int64_t nLabel,
4413 int64_t *pnMantissa,
4414 int64_t *pnExponent)
4415{
4416 QCBORItem Item;
4417
4418 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4419 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4420}
4421
4422
4423
4424void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4425 uint8_t uTagRequirement,
4426 const char *szLabel,
4427 int64_t *pnMantissa,
4428 int64_t *pnExponent)
4429{
4430 QCBORItem Item;
4431
4432 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4433
4434 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4435}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004436#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004437
4438
4439UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4440{
4441 while(uInt & 0xff0000000000UL) {
4442 uInt = uInt << 8;
4443 };
4444
4445 UsefulOutBuf UOB;
4446
4447 UsefulOutBuf_Init(&UOB, Buffer);
4448
4449 while(uInt) {
4450 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4451 uInt = uInt << 8;
4452 }
4453
4454 return UsefulOutBuf_OutUBuf(&UOB);
4455}
4456
4457
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004458#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4459
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004460void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4461 uint8_t uTagRequirement,
4462 int64_t nLabel,
4463 UsefulBuf pBufferForMantissa,
4464 UsefulBufC *pMantissa,
4465 bool *pbIsNegative,
4466 int64_t *pnExponent)
4467{
4468 QCBORItem Item;
4469 QCBORError uErr;
4470
4471 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4472
4473 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4474 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4475 if(uErr != QCBOR_SUCCESS) {
4476 pMe->uLastError = (uint8_t)uErr;
4477 return;
4478 }
4479 }
4480
4481 uint64_t uMantissa;
4482
4483 switch (Item.uDataType) {
4484
4485 case QCBOR_TYPE_DECIMAL_FRACTION:
4486 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4487 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4488 *pbIsNegative = false;
4489 } else {
4490 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4491 *pbIsNegative = true;
4492 }
4493 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4494 *pnExponent = Item.val.expAndMantissa.nExponent;
4495 break;
4496
4497 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4498 *pnExponent = Item.val.expAndMantissa.nExponent;
4499 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4500 *pbIsNegative = false;
4501 break;
4502
4503 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4504 *pnExponent = Item.val.expAndMantissa.nExponent;
4505 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4506 *pbIsNegative = true;
4507 break;
4508
4509 default:
4510 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4511 }
4512}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004513#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004514
4515/*
4516
4517 TODO: do something with this text
4518 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4519 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4520 is the byte offset in the encoded input and a leaf counter for definite
4521 length maps and arrays. Indefinite length maps and arrays are handled
4522 by look ahead for the break.
4523
4524 The view presented to the caller has tags, labels and the chunks of
4525 indefinite length strings aggregated into one decorated data item.
4526
4527 The caller understands the nesting level in pre-order traversal by
4528 the fact that a data item that is a map or array is presented to
4529 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4530 and the nesting level of the next item.
4531
4532 The caller traverse maps and arrays in a special mode that often more convenient
4533 that tracking by nesting level. When an array or map is expected or encountered
4534 the EnterMap or EnteryArray can be called.
4535
4536 When entering a map or array like this, the cursor points to the first
4537 item in the map or array. When exiting, it points to the item after
4538 the map or array, regardless of whether the items in the map or array were
4539 all traversed.
4540
4541 When in a map or array, the cursor functions as normal, but traversal
4542 cannot go past the end of the map or array that was entered. If this
4543 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4544 go past the end of the map or array ExitMap() or ExitArray() must
4545 be called. It can be called any time regardless of the position
4546 of the cursor.
4547
4548 When a map is entered, a special function allows fetching data items
4549 by label. This call will traversal the whole map looking for the
4550 labeled item. The whole map is traversed so as to detect duplicates.
4551 This type of fetching items does not affect the normal traversal
4552 cursor.
4553
4554
4555 When a data item is presented to the caller, the nesting level of the data
4556 item is presented along with the nesting level of the item that would be
4557 next consumed.
4558 */