blob: 2fc0a4f325f53e6d6b3e6f4db01ca59d2e29440a [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 Lundblade5f4e8712020-07-25 11:44:43 -0700120static inline uint32_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 Lundblade085d7952020-07-24 10:26:30 -0700127static inline bool
128DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
129{
130 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
131 return true;
132 } else {
133 return false;
134 }
135}
136
137
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700138inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700139DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700140{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700141 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700142 return true;
143 } else {
144 return false;
145 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146}
147
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700148
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700149inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700150DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700151{
152 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700153 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700154 return false;
155 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700156 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700160 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700161 return true;
162}
163
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700164
Laurence Lundblade642282a2020-06-23 12:00:33 -0700165inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700166DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700167{
168 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700169 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700170 return true;
171 }
172 return false;
173}
174
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700175
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700176inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700177{
178 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
179 return true;
180 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700181 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundblade085d7952020-07-24 10:26:30 -0700188inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700191 /*
192 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
193 larger than DecodeNesting_EnterBoundedMode which keeps it less than
194 uin32_t so the cast is safe.
195 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700196 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700197
198 if(bIsEmpty) {
199 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
200 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201}
202
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700203
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700204inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700206 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700207}
208
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700209
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700211DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700212{
213 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700214 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700215 return false;
216 }
217 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700218 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700222 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700225 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700226 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700227 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700230 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return true;
232}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700233
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700234
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700235inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700236DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700237{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700238 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700239 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
240 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700241 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700242 return false;
243 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700244}
245
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700247inline static bool
248DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700249{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
251 return true;
252 } else {
253 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255}
256
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700257
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700258inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700259DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700260{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700261 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700262 return false;
263 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700264
265 if(pNesting->pCurrentBounded->uLevelType != uType) {
266 return false;
267 }
268
269 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700270}
271
Laurence Lundblade02625d42020-06-25 14:41:41 -0700272
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700273inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700274DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700275{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700276 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700277 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700279
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700280
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700281inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700282DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
283{
284 // Only call on a defnite length array / map
285 pNesting->pCurrent->u.ma.uCountCursor++;
286}
287
288
289inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700290DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
291{
292 pNesting->pCurrent--;
293}
294
Laurence Lundblade02625d42020-06-25 14:41:41 -0700295
296static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700297DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700298{
299 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700301 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
302 }
303
304 // The actual descend
305 pNesting->pCurrent++;
306
307 pNesting->pCurrent->uLevelType = uType;
308
309 return QCBOR_SUCCESS;
310}
311
312
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700313inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700314DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700315{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700316 /*
317 Should only be called on map/array.
318
319 Have descended into this before this is called. The job here is
320 just to mark it in bounded mode.
321 */
Laurence Lundblade085d7952020-07-24 10:26:30 -0700322 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) { //TODO: fix this bounds check
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700323 return QCBOR_ERR_BUFFER_TOO_LARGE;
324 }
325
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700326 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700327
328 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700329
330 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700331}
332
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700333
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700334inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700335DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700336 uint8_t uQCBORType,
337 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700338{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700339 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700340
341 if(uCount == 0) {
342 // Nothing to do for empty definite lenth arrays. They are just are
343 // effectively the same as an item that is not a map or array
344 goto Done;
345 // Empty indefinite length maps and arrays are handled elsewhere
346 }
347
348 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700349 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
350 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
351 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700352 goto Done;
353 }
354
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700355 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357 goto Done;
358 }
359
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700360 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700361 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
362 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700363
364 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 return uError;;
368}
369
370
371static inline void
372DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
373{
374 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
375}
376
377
378static inline void
379DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
380{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700381 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 pNesting->pCurrentBounded--;
383 if(DecodeNesting_IsCurrentBounded(pNesting)) {
384 break;
385 }
386 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700387}
388
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389static inline void
390DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
391{
392 pNesting->pCurrent = pNesting->pCurrentBounded;
393}
394
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700396inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
398 size_t uEndOffset,
399 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700400{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700401 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700402
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700403 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700404 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405 goto Done;
406 }
407
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 // Fill in the new byte string level
409 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700411 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700412
Laurence Lundblade02625d42020-06-25 14:41:41 -0700413 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700414 pNesting->pCurrentBounded = pNesting->pCurrent;
415
416Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 return uError;;
418}
419
Laurence Lundbladed0304932020-06-27 10:59:38 -0700420
421static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700422DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423{
424 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700425}
426
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700427
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700432 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
433 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434}
435
436
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700437inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700439{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700440 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700441 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700443}
444
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700445
Laurence Lundblade02625d42020-06-25 14:41:41 -0700446static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700447DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700448{
449 *pNesting = *pSave;
450}
451
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700454DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700455{
456 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
457}
458
459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462{
463 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
464}
465
466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700468
469const char *TypeStr(uint8_t type)
470{
471 switch(type) {
472 case QCBOR_TYPE_MAP: return " map";
473 case QCBOR_TYPE_ARRAY: return "array";
474 case QCBOR_TYPE_BYTE_STRING: return " bstr";
475 default: return " --- ";
476 }
477}
478
479static char buf[20]; // Not thread safe, but that is OK
480const char *CountString(uint16_t uCount, uint16_t uTotal)
481{
482 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
483 strcpy(buf, "indefinite");
484 } else {
485 sprintf(buf, "%d/%d", uCount, uTotal);
486 }
487 return buf;
488}
489
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700490
Laurence Lundblade02625d42020-06-25 14:41:41 -0700491void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700492{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700493#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495 szName,
496 (uint32_t)pBuf->cursor,
497 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498
499 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700501 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700502 break;
503 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700504
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700505 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700506 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700507 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700508 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700509
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700511 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512 pNesting->pLevels[i].u.bs.uEndOfBstr,
513 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700514
515 } else {
516 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700517 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
518 pNesting->pLevels[i].u.ma.uCountTotal));
519 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
520 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700521 }
522 }
523
524 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700525 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700526 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700527#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700528}
529
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800533 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
534
535 The following four functions are pretty wrappers for invocation of
536 the string allocator supplied by the caller.
537
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800539
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540static inline void
541StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542{
543 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
544}
545
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546// StringAllocator_Reallocate called with pMem NULL is
547// equal to StringAllocator_Allocate()
548static inline UsefulBuf
549StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
550 void *pMem,
551 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552{
553 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
554}
555
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556static inline UsefulBuf
557StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558{
559 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
560}
561
Laurence Lundbladeee851742020-01-08 08:37:05 -0800562static inline void
563StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800564{
565 if(pMe->pfAllocator) {
566 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
567 }
568}
569
570
571
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572/*===========================================================================
573 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800575 See qcbor/qcbor_decode.h for definition of the object
576 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578/*
579 Public function, see header file
580 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581void QCBORDecode_Init(QCBORDecodeContext *me,
582 UsefulBufC EncodedCBOR,
583 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584{
585 memset(me, 0, sizeof(QCBORDecodeContext));
586 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 // Don't bother with error check on decode mode. If a bad value is
588 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700589 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700590 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700591 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700592 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700593 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700594}
595
596
597/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598 Public function, see header file
599 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
601 QCBORStringAllocate pfAllocateFunction,
602 void *pAllocateContext,
603 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
606 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
607 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700608}
609
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610
611/*
612 Public function, see header file
613 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700614void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800615 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700616{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700617 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700618 (void)pMe;
619 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700620}
621
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622
623/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 This decodes the fundamental part of a CBOR data item, the type and
625 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 This does the network->host byte order conversion. The conversion
630 here also results in the conversion for floats in addition to that
631 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700633 This returns:
634 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800635
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800637 tags and floats and length for strings and arrays
638
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800640 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800641
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800642 The int type is preferred to uint8_t for some variables as this
643 avoids integer promotions, can reduce code size and makes
644 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
647 int *pnMajorType,
648 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700651 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800652
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800654 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800657 const int nTmpMajorType = nInitialByte >> 5;
658 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800660 // Where the number or argument accumulates
661 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800662
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700664 // Need to get 1,2,4 or 8 additional argument bytes. Map
665 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800666 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800668 // Loop getting all the bytes in the argument
669 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800671 // This shift and add gives the endian conversion
672 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
673 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 // The reserved and thus-far unused additional info values
676 nReturn = QCBOR_ERR_UNSUPPORTED;
677 goto Done;
678 } else {
679 // Less than 24, additional info is argument or 31, an indefinite length
680 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 if(UsefulInputBuf_GetError(pUInBuf)) {
685 nReturn = QCBOR_ERR_HIT_END;
686 goto Done;
687 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 // All successful if we got here.
690 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800691 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800692 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695Done:
696 return nReturn;
697}
698
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701 CBOR doesn't explicitly specify two's compliment for integers but all
702 CPUs use it these days and the test vectors in the RFC are so. All
703 integers in the CBOR structure are positive and the major type
704 indicates positive or negative. CBOR can express positive integers
705 up to 2^x - 1 where x is the number of bits and negative integers
706 down to 2^x. Note that negative numbers can be one more away from
707 zero than positive. Stdint, as far as I can tell, uses two's
708 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 used carefully here, and in particular why it isn't used in the interface.
712 Also see
713 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
714
715 Int is used for values that need less than 16-bits and would be subject
716 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800718inline static QCBORError
719DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700721 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
724 if (uNumber <= INT64_MAX) {
725 pDecodedItem->val.int64 = (int64_t)uNumber;
726 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800727
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728 } else {
729 pDecodedItem->val.uint64 = uNumber;
730 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 }
733 } else {
734 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800735 // CBOR's representation of negative numbers lines up with the
736 // two-compliment representation. A negative integer has one
737 // more in range than a positive integer. INT64_MIN is
738 // equal to (-INT64_MAX) - 1.
739 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 } else {
743 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000744 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745 nReturn = QCBOR_ERR_INT_OVERFLOW;
746 }
747 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800748
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749 return nReturn;
750}
751
752// Make sure #define value line up as DecodeSimple counts on this.
753#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
754#error QCBOR_TYPE_FALSE macro value wrong
755#endif
756
757#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
758#error QCBOR_TYPE_TRUE macro value wrong
759#endif
760
761#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
762#error QCBOR_TYPE_NULL macro value wrong
763#endif
764
765#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
766#error QCBOR_TYPE_UNDEF macro value wrong
767#endif
768
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700769#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
770#error QCBOR_TYPE_BREAK macro value wrong
771#endif
772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
774#error QCBOR_TYPE_DOUBLE macro value wrong
775#endif
776
777#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
778#error QCBOR_TYPE_FLOAT macro value wrong
779#endif
780
781/*
782 Decode true, false, floats, break...
783 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800784inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800785DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700786{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700787 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800790 // above make sure uAdditionalInfo values line up with uDataType values.
791 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
792 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800795 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
796 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700798 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700799 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
800 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700801 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700802 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
804 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700805 break;
806 case DOUBLE_PREC_FLOAT:
807 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700808 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700809 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 case CBOR_SIMPLEV_FALSE: // 20
812 case CBOR_SIMPLEV_TRUE: // 21
813 case CBOR_SIMPLEV_NULL: // 22
814 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700815 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 case CBOR_SIMPLEV_ONEBYTE: // 24
819 if(uNumber <= CBOR_SIMPLE_BREAK) {
820 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700821 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 goto Done;
823 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800824 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 default: // 0-19
828 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800829 /*
830 DecodeTypeAndNumber will make uNumber equal to
831 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
832 safe because the 2, 4 and 8 byte lengths of uNumber are in
833 the double/float cases above
834 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 pDecodedItem->val.uSimple = (uint8_t)uNumber;
836 break;
837 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839Done:
840 return nReturn;
841}
842
843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530845 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800847inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
848 int nMajorType,
849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800873 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530874 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800875 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530876 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700877 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530878 goto Done;
879 }
880 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800881 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882 } else {
883 // Normal case with no string allocator
884 pDecodedItem->val.string = Bytes;
885 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800886 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 // Cast because ternary operator causes promotion to integer
888 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
889 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 return nReturn;
893}
894
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897
898
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899
900
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901// Make sure the constants align as this is assumed by
902// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
904#error QCBOR_TYPE_ARRAY value not lined up with major type
905#endif
906#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
907#error QCBOR_TYPE_MAP value not lined up with major type
908#endif
909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800911 This gets a single data item and decodes it including preceding
912 optional tagging. This does not deal with arrays and maps and nesting
913 except to decode the data item introducing them. Arrays and maps are
914 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundbladeee851742020-01-08 08:37:05 -0800916 Errors detected here include: an array that is too long to decode,
917 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800919static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
920 QCBORItem *pDecodedItem,
921 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700923 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800924
Laurence Lundbladeee851742020-01-08 08:37:05 -0800925 /*
926 Get the major type and the number. Number could be length of more
927 bytes or the value depending on the major type nAdditionalInfo is
928 an encoding of the length of the uNumber and is needed to decode
929 floats and doubles
930 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700932 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800933 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700935 memset(pDecodedItem, 0, sizeof(QCBORItem));
936
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundbladeee851742020-01-08 08:37:05 -0800939 // Error out here if we got into trouble on the type and number. The
940 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700941 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladeee851742020-01-08 08:37:05 -0800945 // At this point the major type and the value are valid. We've got
946 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
949 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700951 nReturn = QCBOR_ERR_BAD_INT;
952 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800953 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700954 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
958 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
960 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
961 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
962 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530963 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700964 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700966 }
967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
970 case CBOR_MAJOR_TYPE_MAP: // Major type 5
971 // Record the number of items in the array or map
972 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
973 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
974 goto Done;
975 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700977 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800979 // type conversion OK because of check above
980 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800982 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
984 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700989 nReturn = QCBOR_ERR_BAD_INT;
990 } else {
991 pDecodedItem->val.uTagV = uNumber;
992 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
993 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800995
Laurence Lundbladeee851742020-01-08 08:37:05 -0800996 case CBOR_MAJOR_TYPE_SIMPLE:
997 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800998 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 default:
1002 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 nReturn = QCBOR_ERR_UNSUPPORTED;
1004 break;
1005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007Done:
1008 return nReturn;
1009}
1010
1011
1012
1013/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001014 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001015 individual chunk items together into one QCBORItem using the string
1016 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301018 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020static inline QCBORError
1021GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001023 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001024
1025 // Get pointer to string allocator. First use is to pass it to
1026 // GetNext_Item() when option is set to allocate for *every* string.
1027 // Second use here is to allocate space to coallese indefinite
1028 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001029 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1030 &(me->StringAllocator) :
1031 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001033 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001034 nReturn = GetNext_Item(&(me->InBuf),
1035 pDecodedItem,
1036 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 if(nReturn) {
1038 goto Done;
1039 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301042 // code in this function from here down can be eliminated. Run tests, except
1043 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001045 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001046 const uint8_t uStringType = pDecodedItem->uDataType;
1047 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048 goto Done; // no need to do any work here on non-string types
1049 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001051 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301052 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001053 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301056 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001057 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1059 goto Done;
1060 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001061
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001062 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001063 UsefulBufC FullString = NULLUsefulBufC;
1064
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001066 // Get item for next chunk
1067 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001068 // NULL string allocator passed here. Do not need to allocate
1069 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001070 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001072 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301075 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001076 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301079 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 break;
1081 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001082
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001083 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301084 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001085 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001086 if(StringChunkItem.uDataType != uStringType ||
1087 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001088 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 break;
1090 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001091
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301092 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 // The first time throurgh FullString.ptr is NULL and this is
1094 // equivalent to StringAllocator_Allocate()
1095 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1096 UNCONST_POINTER(FullString.ptr),
1097 FullString.len + StringChunkItem.val.string.len);
1098
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301100 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001101 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 break;
1103 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001104
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001105 // Copy new string chunk at the end of string so far.
1106 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001109 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1110 // Getting the item failed, clean up the allocated memory
1111 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001114Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 return nReturn;
1116}
1117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001119static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1120 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001121 return uTagVal;
1122 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001123 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001124 return me->auMappedTags[x];
1125 }
1126}
1127
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001128/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001129 Gets all optional tag data items preceding a data item that is not an
1130 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001132static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001135 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001136
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001137 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1138 CBOR_TAG_INVALID16,
1139 CBOR_TAG_INVALID16,
1140 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001141
Laurence Lundblade59289e52019-12-30 13:44:37 -08001142 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001143 for(;;) {
1144 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001145 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001149 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1150 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001152 break;
1153 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001155 // Is there room for the tag in the tags list?
1156 size_t uTagIndex;
1157 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001158 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001159 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160 }
1161 }
1162 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001163 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001165
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001166 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001167 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001171 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001172 break;
1173 }
1174 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001175 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001176 break;
1177 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001178 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1180 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001181 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1182 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001183 }
1184
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001185 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001187 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188
1189 } else {
1190 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 }
1192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194Done:
1195 return nReturn;
1196}
1197
1198
1199/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001200 This layer takes care of map entries. It combines the label and data
1201 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001202 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001203static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001204GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001205{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001206 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001208 if(nReturn)
1209 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001211 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001212 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001213 goto Done;
1214 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001216 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1217 // In a map and caller wants maps decoded, not treated as arrays
1218
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001219 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001220 // If in a map and the right decoding mode, get the label
1221
Laurence Lundbladeee851742020-01-08 08:37:05 -08001222 // Save label in pDecodedItem and get the next which will
1223 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001224 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001225 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001226 if(nReturn)
1227 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301229 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001230
1231 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1232 // strings are always good labels
1233 pDecodedItem->label.string = LabelItem.val.string;
1234 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1235 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001236 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001237 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1238 goto Done;
1239 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1240 pDecodedItem->label.int64 = LabelItem.val.int64;
1241 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1242 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1243 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1244 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1245 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1246 pDecodedItem->label.string = LabelItem.val.string;
1247 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1248 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1249 } else {
1250 // label is not an int or a string. It is an arrray
1251 // or a float or such and this implementation doesn't handle that.
1252 // Also, tags on labels are ignored.
1253 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1254 goto Done;
1255 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001256 }
1257 } else {
1258 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001259 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1260 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1261 goto Done;
1262 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001263 // Decoding a map as an array
1264 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001265 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1266 // Cast is needed because of integer promotion
1267 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001268 }
1269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001271Done:
1272 return nReturn;
1273}
1274
1275
Laurence Lundblade02625d42020-06-25 14:41:41 -07001276/*
1277 See if next item is a CBOR break. If it is, it is consumed,
1278 if not it is not consumed.
1279*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001280static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001281NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1282{
1283 *pbNextIsBreak = false;
1284 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001285 QCBORItem Peek;
1286 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1287 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1288 if(uReturn != QCBOR_SUCCESS) {
1289 return uReturn;
1290 }
1291 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001292 // It is not a break, rewind so it can be processed normally.
1293 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001294 } else {
1295 *pbNextIsBreak = true;
1296 }
1297 }
1298
1299 return QCBOR_SUCCESS;
1300}
1301
1302
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001304 An item was just consumed, now figure out if it was the
1305 end of an array or map that can be closed out. That
1306 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001308static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001309{
1310 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001311
Laurence Lundblade642282a2020-06-23 12:00:33 -07001312 /* This loops ascending nesting levels as long as there is ascending to do */
1313 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1314
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001315 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001316 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001317 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1318 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001319 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320 break;
1321 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001322 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001323
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001324 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001325 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001326 bool bIsBreak = false;
1327 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1328 if(uReturn != QCBOR_SUCCESS) {
1329 goto Done;
1330 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331
1332 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001333 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 break;
1335 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001337 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001338 /*
1339 Break occurred inside a bstr-wrapped CBOR or
1340 in the top level sequence. This is always an
1341 error because neither are an indefinte length
1342 map/array.
1343 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001344 uReturn = QCBOR_ERR_BAD_BREAK;
1345 goto Done;
1346 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001347
Laurence Lundblade02625d42020-06-25 14:41:41 -07001348 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001349 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001350
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001352
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001353 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001354 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001355 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001356 if(bMarkEnd) {
1357 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001358 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001359
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001360 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001361 break;
1362 }
1363
1364 /* Finally, actually ascend one level. */
1365 DecodeNesting_Ascend(&(pMe->nesting));
1366 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001367
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001368 uReturn = QCBOR_SUCCESS;
1369
1370Done:
1371 return uReturn;
1372}
1373
1374
1375/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001376 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001377 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1378 indefinte length maps and arrays by looking at the item count or
1379 finding CBOR breaks. It detects the ends of the top-level sequence
1380 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001381 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001382static QCBORError
1383QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001384{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001385 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001386 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001387
Laurence Lundblade642282a2020-06-23 12:00:33 -07001388 /*
1389 If out of bytes to consume, it is either the end of the top-level
1390 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001391
Laurence Lundblade642282a2020-06-23 12:00:33 -07001392 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1393 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1394 CBOR is exited, the length is set back to the top-level's length
1395 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001397 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001398 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001399 goto Done;
1400 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001401
Laurence Lundblade642282a2020-06-23 12:00:33 -07001402 /*
1403 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001404 array. The check for the end of an indefinite length array is
1405 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001406 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001407 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001408 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001409 goto Done;
1410 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001411
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001412 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001413 uReturn = GetNext_MapEntry(me, pDecodedItem);
1414 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001415 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001416 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301417
Laurence Lundblade642282a2020-06-23 12:00:33 -07001418 /*
1419 Breaks ending arrays/maps are always processed at the end of this
1420 function. They should never show up here.
1421 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301422 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001423 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301424 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301425 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001426
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427 /*
1428 Record the nesting level for this data item before processing any
1429 of decrementing and descending.
1430 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001431 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001432
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001434 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001435 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001436 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001437 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001438
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001439 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001440 of in the next chunk of code.
1441
1442 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001443 encloses them so a decrement needs to be done for them too, but
1444 that is done only when all the items in them have been
1445 processed, not when they are opened with the exception of an
1446 empty map or array.
1447 */
1448 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1449 pDecodedItem->uDataType,
1450 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001451 if(uReturn != QCBOR_SUCCESS) {
1452 goto Done;
1453 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001454 }
1455
Laurence Lundblade02625d42020-06-25 14:41:41 -07001456 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1457 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1458 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001459 /*
1460 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001461 - A non-aggregate like an integer or string
1462 - An empty definite length map or array
1463 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001465 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 definite length map/array and break detection for an indefinite
1467 length map/array. If the end of the map/array was reached, then
1468 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001469 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001470 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001471 if(uReturn) {
1472 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001473 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301474 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001475
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001476 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001478 Tell the caller what level is next. This tells them what
1479 maps/arrays were closed out and makes it possible for them to
1480 reconstruct the tree with just the information returned in
1481 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001482 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001483 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001484 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001485 pDecodedItem->uNextNestLevel = 0;
1486 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001487 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001488 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001489
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001490Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001491 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001492 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001493 memset(pDecodedItem, 0, sizeof(QCBORItem));
1494 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001495 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001496}
1497
1498
Laurence Lundblade59289e52019-12-30 13:44:37 -08001499/*
1500 Mostly just assign the right data type for the date string.
1501 */
1502inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1503{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001504 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1505 return QCBOR_ERR_BAD_OPT_TAG;
1506 }
1507
1508 const UsefulBufC Temp = pDecodedItem->val.string;
1509 pDecodedItem->val.dateString = Temp;
1510 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1511 return QCBOR_SUCCESS;
1512}
1513
1514
1515/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001516 The epoch formatted date. Turns lots of different forms of encoding
1517 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001518 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001519static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001520{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001521 QCBORError nReturn = QCBOR_SUCCESS;
1522
1523 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1524
1525 switch (pDecodedItem->uDataType) {
1526
1527 case QCBOR_TYPE_INT64:
1528 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1529 break;
1530
1531 case QCBOR_TYPE_UINT64:
1532 if(pDecodedItem->val.uint64 > INT64_MAX) {
1533 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1534 goto Done;
1535 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001536 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001537 break;
1538
1539 case QCBOR_TYPE_DOUBLE:
1540 {
1541 // This comparison needs to be done as a float before
1542 // conversion to an int64_t to be able to detect doubles
1543 // that are too large to fit into an int64_t. A double
1544 // has 52 bits of preceision. An int64_t has 63. Casting
1545 // INT64_MAX to a double actually causes a round up which
1546 // is bad and wrong for the comparison because it will
1547 // allow conversion of doubles that can't fit into a
1548 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1549 // the cutoff point as if that rounds up in conversion to
1550 // double it will still be less than INT64_MAX. 0x7ff is
1551 // picked because it has 11 bits set.
1552 //
1553 // INT64_MAX seconds is on the order of 10 billion years,
1554 // and the earth is less than 5 billion years old, so for
1555 // most uses this conversion error won't occur even though
1556 // doubles can go much larger.
1557 //
1558 // Without the 0x7ff there is a ~30 minute range of time
1559 // values 10 billion years in the past and in the future
1560 // where this this code would go wrong.
1561 const double d = pDecodedItem->val.dfnum;
1562 if(d > (double)(INT64_MAX - 0x7ff)) {
1563 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1564 goto Done;
1565 }
1566 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1567 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1568 }
1569 break;
1570
1571 default:
1572 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1573 goto Done;
1574 }
1575 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1576
1577Done:
1578 return nReturn;
1579}
1580
1581
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001582/*
1583 Mostly just assign the right data type for the bignum.
1584 */
1585inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1586{
1587 // Stack Use: UsefulBuf 1 -- 16
1588 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1589 return QCBOR_ERR_BAD_OPT_TAG;
1590 }
1591 const UsefulBufC Temp = pDecodedItem->val.string;
1592 pDecodedItem->val.bigNum = Temp;
1593 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1594 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1595 : QCBOR_TYPE_NEGBIGNUM);
1596 return QCBOR_SUCCESS;
1597}
1598
1599
Laurence Lundblade59289e52019-12-30 13:44:37 -08001600#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1601/*
1602 Decode decimal fractions and big floats.
1603
1604 When called pDecodedItem must be the array that is tagged as a big
1605 float or decimal fraction, the array that has the two members, the
1606 exponent and mantissa.
1607
1608 This will fetch and decode the exponent and mantissa and put the
1609 result back into pDecodedItem.
1610 */
1611inline static QCBORError
1612QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1613{
1614 QCBORError nReturn;
1615
1616 // --- Make sure it is an array; track nesting level of members ---
1617 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1618 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1619 goto Done;
1620 }
1621
1622 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001623 // definite length arrays, but not for indefnite. Instead remember
1624 // the nesting level the two integers must be at, which is one
1625 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001626 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1627
1628 // --- Is it a decimal fraction or a bigfloat? ---
1629 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1630 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1631
1632 // --- Get the exponent ---
1633 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001634 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001635 if(nReturn != QCBOR_SUCCESS) {
1636 goto Done;
1637 }
1638 if(exponentItem.uNestingLevel != nNestLevel) {
1639 // Array is empty or a map/array encountered when expecting an int
1640 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1641 goto Done;
1642 }
1643 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1644 // Data arriving as an unsigned int < INT64_MAX has been converted
1645 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1646 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1647 // will be too large for this to handle and thus an error that will
1648 // get handled in the next else.
1649 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1650 } else {
1651 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1652 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1653 goto Done;
1654 }
1655
1656 // --- Get the mantissa ---
1657 QCBORItem mantissaItem;
1658 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1659 if(nReturn != QCBOR_SUCCESS) {
1660 goto Done;
1661 }
1662 if(mantissaItem.uNestingLevel != nNestLevel) {
1663 // Mantissa missing or map/array encountered when expecting number
1664 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1665 goto Done;
1666 }
1667 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1668 // Data arriving as an unsigned int < INT64_MAX has been converted
1669 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1670 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1671 // will be too large for this to handle and thus an error that
1672 // will get handled in an else below.
1673 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1674 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1675 // Got a good big num mantissa
1676 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1677 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001678 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1679 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1680 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001681 } else {
1682 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1683 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1684 goto Done;
1685 }
1686
1687 // --- Check that array only has the two numbers ---
1688 if(mantissaItem.uNextNestLevel == nNestLevel) {
1689 // Extra items in the decimal fraction / big num
1690 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1691 goto Done;
1692 }
1693
1694Done:
1695
1696 return nReturn;
1697}
1698#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1699
1700
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001701
1702/*
1703 */
1704inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1705{
1706 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1707 return QCBOR_ERR_BAD_OPT_TAG;
1708 }
1709 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1710 return QCBOR_SUCCESS;
1711}
1712
1713
1714inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1715{
1716 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1717 return QCBOR_ERR_BAD_OPT_TAG;
1718 }
1719 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1720 return QCBOR_SUCCESS;
1721}
1722
1723
1724inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1725{
1726 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1727 return QCBOR_ERR_BAD_OPT_TAG;
1728 }
1729 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1730 return QCBOR_SUCCESS;
1731}
1732
1733
1734inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1735{
1736 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1737 return QCBOR_ERR_BAD_OPT_TAG;
1738 }
1739 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1740 return QCBOR_SUCCESS;
1741}
1742
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001743inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1744{
1745 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1746 return QCBOR_ERR_BAD_OPT_TAG;
1747 }
1748 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1749 return QCBOR_SUCCESS;
1750}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001751
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001752
1753inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1754{
1755 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1756 return QCBOR_ERR_BAD_OPT_TAG;
1757 }
1758 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1759 return QCBOR_SUCCESS;
1760}
1761
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001762inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1763{
1764 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1765 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1766 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1767 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1768 } else {
1769 return QCBOR_ERR_BAD_OPT_TAG;
1770 }
1771 return QCBOR_SUCCESS;
1772}
1773
1774
1775/*
1776 */
1777inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1778{
1779 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1780 return QCBOR_ERR_BAD_OPT_TAG;
1781 }
1782 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1783 return QCBOR_SUCCESS;
1784}
1785
1786
Laurence Lundblade59289e52019-12-30 13:44:37 -08001787/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001788 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001790QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001791QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001792{
1793 QCBORError nReturn;
1794
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001795 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001796 if(nReturn != QCBOR_SUCCESS) {
1797 goto Done;
1798 }
1799
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001800 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1801 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001802
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001803 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001804 nReturn = DecodeDateString(pDecodedItem);
1805 break;
1806
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001807 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001808 nReturn = DecodeDateEpoch(pDecodedItem);
1809 break;
1810
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001811 case CBOR_TAG_POS_BIGNUM:
1812 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001813 nReturn = DecodeBigNum(pDecodedItem);
1814 break;
1815
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001816 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1817 case CBOR_TAG_DECIMAL_FRACTION:
1818 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001819 // For aggregate tagged types, what goes into pTags is only collected
1820 // from the surrounding data item, not the contents, so pTags is not
1821 // passed on here.
1822
1823 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1824 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001825 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001826
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001827 case CBOR_TAG_CBOR:
1828 nReturn = DecodeWrappedCBOR(pDecodedItem);
1829 break;
1830
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001831 case CBOR_TAG_CBOR_SEQUENCE:
1832 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1833 break;
1834
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001835 case CBOR_TAG_URI:
1836 nReturn = DecodeURI(pDecodedItem);
1837 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001838
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001839 case CBOR_TAG_B64URL:
1840 nReturn = DecodeB64URL(pDecodedItem);
1841 break;
1842
1843 case CBOR_TAG_B64:
1844 nReturn = DecodeB64(pDecodedItem);
1845 break;
1846
1847 case CBOR_TAG_MIME:
1848 case CBOR_TAG_BINARY_MIME:
1849 nReturn = DecodeMIME(pDecodedItem);
1850 break;
1851
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001852 case CBOR_TAG_REGEX:
1853 nReturn = DecodeRegex(pDecodedItem);
1854 break;
1855
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001856 case CBOR_TAG_BIN_UUID:
1857 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001858 break;
1859
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001860 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001861 // The end of the tag list or no tags
1862 // Successful exit from the loop.
1863 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001864
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001865 default:
1866 // A tag that is not understood
1867 // A successful exit from the loop
1868 goto Done;
1869
1870 }
1871 if(nReturn != QCBOR_SUCCESS) {
1872 goto Done;
1873 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001874 }
1875
1876Done:
1877 if(nReturn != QCBOR_SUCCESS) {
1878 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1879 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1880 }
1881 return nReturn;
1882}
1883
1884
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001885QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1886{
1887 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1888
1889 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1890
1891 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1892
1893 return uErr;
1894}
1895
1896
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001898 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001899 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001900QCBORError
1901QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1902 QCBORItem *pDecodedItem,
1903 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001904{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001905 QCBORError nReturn;
1906
1907 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1908 if(nReturn != QCBOR_SUCCESS) {
1909 return nReturn;
1910 }
1911
1912 if(pTags != NULL) {
1913 pTags->uNumUsed = 0;
1914 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001915 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001916 break;
1917 }
1918 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1919 return QCBOR_ERR_TOO_MANY_TAGS;
1920 }
1921 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1922 pTags->uNumUsed++;
1923 }
1924 }
1925
1926 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001927}
1928
1929
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001930/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301931 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301932 next one down. If a layer has no work to do for a particular item
1933 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001934
Laurence Lundblade59289e52019-12-30 13:44:37 -08001935 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1936 tagged data items, turning them into the local C representation.
1937 For the most simple it is just associating a QCBOR_TYPE with the data. For
1938 the complex ones that an aggregate of data items, there is some further
1939 decoding and a little bit of recursion.
1940
1941 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301942 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301943 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001944 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001945
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301946 - GetNext_MapEntry -- This handles the combining of two
1947 items, the label and the data, that make up a map entry.
1948 It only does work on maps. It combines the label and data
1949 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001950
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1952 tags into bit flags associated with the data item. No actual decoding
1953 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001954
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301956 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301957 string allocater to create contiguous space for the item. It
1958 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001959
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1961 atomic data item has a "major type", an integer "argument" and optionally
1962 some content. For text and byte strings, the content is the bytes
1963 that make up the string. These are the smallest data items that are
1964 considered to be well-formed. The content may also be other data items in
1965 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001966
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001967 Roughly this takes 300 bytes of stack for vars. Need to
1968 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001969
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301970 */
1971
1972
1973/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001974 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001975 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001976int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001977 const QCBORItem *pItem,
1978 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001979{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001980 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001981 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001982 break;
1983 }
1984 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1985 return 1;
1986 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001987 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001988
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001989 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001990}
1991
1992
1993/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001994 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001995 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001996QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001997{
Laurence Lundblade085d7952020-07-24 10:26:30 -07001998 QCBORError uReturn = me->uLastError;
1999
2000 if(uReturn != QCBOR_SUCCESS) {
2001 goto Done;
2002 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002003
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002004 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002005 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002006 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002007 goto Done;
2008 }
2009
2010 // Error out if not all the bytes are consumed
2011 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002012 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002013 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002014
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002015Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302016 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002017 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002018 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002019
Laurence Lundblade085d7952020-07-24 10:26:30 -07002020 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002021}
2022
2023
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002024/*
2025Public function, see header qcbor/qcbor_decode.h file
2026*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002027uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2028 const QCBORItem *pItem,
2029 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002030{
2031 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2032 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002033 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002034 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002035 }
2036}
2037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002038
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002039/*
2040
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002041Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002042
Laurence Lundbladeee851742020-01-08 08:37:05 -08002043 - Hit end of input before it was expected while decoding type and
2044 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002046 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002047
Laurence Lundbladeee851742020-01-08 08:37:05 -08002048 - Hit end of input while decoding a text or byte string
2049 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002050
Laurence Lundbladeee851742020-01-08 08:37:05 -08002051 - Encountered conflicting tags -- e.g., an item is tagged both a date
2052 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundbladeee851742020-01-08 08:37:05 -08002054 - Encontered an array or mapp that has too many items
2055 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002056
Laurence Lundbladeee851742020-01-08 08:37:05 -08002057 - Encountered array/map nesting that is too deep
2058 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002059
Laurence Lundbladeee851742020-01-08 08:37:05 -08002060 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2061 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002062
Laurence Lundbladeee851742020-01-08 08:37:05 -08002063 - The type of a map label is not a string or int
2064 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002065
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002066 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002067
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002068 */
2069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002070
2071
Laurence Lundbladef6531662018-12-04 10:42:22 +09002072
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002073/* ===========================================================================
2074 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002075
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002076 This implements a simple sting allocator for indefinite length
2077 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2078 implements the function type QCBORStringAllocate and allows easy
2079 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002080
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002081 This particular allocator is built-in for convenience. The caller
2082 can implement their own. All of this following code will get
2083 dead-stripped if QCBORDecode_SetMemPool() is not called.
2084
2085 This is a very primitive memory allocator. It does not track
2086 individual allocations, only a high-water mark. A free or
2087 reallocation must be of the last chunk allocated.
2088
2089 The size of the pool and offset to free memory are packed into the
2090 first 8 bytes of the memory pool so we don't have to keep them in
2091 the decode context. Since the address of the pool may not be
2092 aligned, they have to be packed and unpacked as if they were
2093 serialized data of the wire or such.
2094
2095 The sizes packed in are uint32_t to be the same on all CPU types
2096 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002097 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002098
2099
Laurence Lundbladeee851742020-01-08 08:37:05 -08002100static inline int
2101MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002102{
2103 // Use of UsefulInputBuf is overkill, but it is convenient.
2104 UsefulInputBuf UIB;
2105
Laurence Lundbladeee851742020-01-08 08:37:05 -08002106 // Just assume the size here. It was checked during SetUp so
2107 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002108 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2109 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2110 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2111 return UsefulInputBuf_GetError(&UIB);
2112}
2113
2114
Laurence Lundbladeee851742020-01-08 08:37:05 -08002115static inline int
2116MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002117{
2118 // Use of UsefulOutBuf is overkill, but convenient. The
2119 // length check performed here is useful.
2120 UsefulOutBuf UOB;
2121
2122 UsefulOutBuf_Init(&UOB, Pool);
2123 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2124 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2125 return UsefulOutBuf_GetError(&UOB);
2126}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002127
2128
2129/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002130 Internal function for an allocation, reallocation free and destuct.
2131
2132 Having only one function rather than one each per mode saves space in
2133 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002134
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002135 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2136 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002137static UsefulBuf
2138MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002139{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002140 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002141
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002142 uint32_t uPoolSize;
2143 uint32_t uFreeOffset;
2144
2145 if(uNewSize > UINT32_MAX) {
2146 // This allocator is only good up to 4GB. This check should
2147 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2148 goto Done;
2149 }
2150 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2151
2152 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2153 goto Done;
2154 }
2155
2156 if(uNewSize) {
2157 if(pMem) {
2158 // REALLOCATION MODE
2159 // Calculate pointer to the end of the memory pool. It is
2160 // assumed that pPool + uPoolSize won't wrap around by
2161 // assuming the caller won't pass a pool buffer in that is
2162 // not in legitimate memory space.
2163 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2164
2165 // Check that the pointer for reallocation is in the range of the
2166 // pool. This also makes sure that pointer math further down
2167 // doesn't wrap under or over.
2168 if(pMem >= pPool && pMem < pPoolEnd) {
2169 // Offset to start of chunk for reallocation. This won't
2170 // wrap under because of check that pMem >= pPool. Cast
2171 // is safe because the pool is always less than UINT32_MAX
2172 // because of check in QCBORDecode_SetMemPool().
2173 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2174
2175 // Check to see if the allocation will fit. uPoolSize -
2176 // uMemOffset will not wrap under because of check that
2177 // pMem is in the range of the uPoolSize by check above.
2178 if(uNewSize <= uPoolSize - uMemOffset) {
2179 ReturnValue.ptr = pMem;
2180 ReturnValue.len = uNewSize;
2181
2182 // Addition won't wrap around over because uNewSize was
2183 // checked to be sure it is less than the pool size.
2184 uFreeOffset = uMemOffset + uNewSize32;
2185 }
2186 }
2187 } else {
2188 // ALLOCATION MODE
2189 // uPoolSize - uFreeOffset will not underflow because this
2190 // pool implementation makes sure uFreeOffset is always
2191 // smaller than uPoolSize through this check here and
2192 // reallocation case.
2193 if(uNewSize <= uPoolSize - uFreeOffset) {
2194 ReturnValue.len = uNewSize;
2195 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002196 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002197 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002198 }
2199 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002200 if(pMem) {
2201 // FREE MODE
2202 // Cast is safe because of limit on pool size in
2203 // QCBORDecode_SetMemPool()
2204 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2205 } else {
2206 // DESTRUCT MODE
2207 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002208 }
2209 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002211 UsefulBuf Pool = {pPool, uPoolSize};
2212 MemPool_Pack(Pool, uFreeOffset);
2213
2214Done:
2215 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002216}
2217
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002218
Laurence Lundbladef6531662018-12-04 10:42:22 +09002219/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002220 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002221 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002222QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2223 UsefulBuf Pool,
2224 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002225{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002226 // The pool size and free mem offset are packed into the beginning
2227 // of the pool memory. This compile time check make sure the
2228 // constant in the header is correct. This check should optimize
2229 // down to nothing.
2230 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002231 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002234 // The pool size and free offset packed in to the beginning of pool
2235 // memory are only 32-bits. This check will optimize out on 32-bit
2236 // machines.
2237 if(Pool.len > UINT32_MAX) {
2238 return QCBOR_ERR_BUFFER_TOO_LARGE;
2239 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002240
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002241 // This checks that the pool buffer given is big enough.
2242 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2243 return QCBOR_ERR_BUFFER_TOO_SMALL;
2244 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002246 pMe->StringAllocator.pfAllocator = MemPool_Function;
2247 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2248 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002249
Laurence Lundblade30816f22018-11-10 13:40:22 +07002250 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002251}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002252
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002253
2254
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002255
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002256
2257
2258/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002259 Consume an entire map or array (and do next to
2260 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002261 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002262static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002263ConsumeItem(QCBORDecodeContext *pMe,
2264 const QCBORItem *pItemToConsume,
2265 uint_fast8_t *puNextNestLevel)
2266{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002268 QCBORItem Item;
2269
Laurence Lundblade02625d42020-06-25 14:41:41 -07002270 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002271
Laurence Lundblade02625d42020-06-25 14:41:41 -07002272 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002273 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002274
Laurence Lundblade1341c592020-04-11 14:19:05 -07002275 /* This works for definite and indefinite length
2276 * maps and arrays by using the nesting level
2277 */
2278 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002279 uReturn = QCBORDecode_GetNext(pMe, &Item);
2280 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281 goto Done;
2282 }
2283 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002284
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285 if(puNextNestLevel != NULL) {
2286 *puNextNestLevel = Item.uNextNestLevel;
2287 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002288 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002289
Laurence Lundblade1341c592020-04-11 14:19:05 -07002290 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002291 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002292 if(puNextNestLevel != NULL) {
2293 /* Just pass the nesting level through */
2294 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2295 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002296 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002297 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002298
2299Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002300 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301}
2302
2303
Laurence Lundblade1341c592020-04-11 14:19:05 -07002304/* Return true if the labels in Item1 and Item2 are the same.
2305 Works only for integer and string labels. Returns false
2306 for any other type. */
2307static inline bool
2308MatchLabel(QCBORItem Item1, QCBORItem Item2)
2309{
2310 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2311 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2312 return true;
2313 }
2314 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002315 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002316 return true;
2317 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002318 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002319 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2320 return true;
2321 }
2322 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2323 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2324 return true;
2325 }
2326 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002327
Laurence Lundblade1341c592020-04-11 14:19:05 -07002328 /* Other label types are never matched */
2329 return false;
2330}
2331
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002332
2333/*
2334 Returns true if Item1 and Item2 are the same type
2335 or if either are of QCBOR_TYPE_ANY.
2336 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002337static inline bool
2338MatchType(QCBORItem Item1, QCBORItem Item2)
2339{
2340 if(Item1.uDataType == Item2.uDataType) {
2341 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002342 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002343 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002344 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002345 return true;
2346 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002347 return false;
2348}
2349
2350
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002351/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002352 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002353
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002354 @param[in] pMe The decode context to search.
2355 @param[in,out] pItemArray The items to search for and the items found.
2356 @param[out] puOffset Byte offset of last item matched.
2357 @param[in] pCBContext Context for the not-found item call back.
2358 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002359
2360 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2361
2362 @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.
2363
2364 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2365
2366 @retval Also errors returned by QCBORDecode_GetNext().
2367
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002368 On input pItemArray contains a list of labels and data types
2369 of items to be found.
2370
2371 On output the fully retrieved items are filled in with
2372 values and such. The label was matched, so it never changes.
2373
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002374 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002376static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002377MapSearch(QCBORDecodeContext *pMe,
2378 QCBORItem *pItemArray,
2379 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002380 void *pCBContext,
2381 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002382{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002383 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002384 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002385
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002386 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002387 uReturn = pMe->uLastError;
2388 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002389 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002390
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002391 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002392 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2393 /* QCBOR_TYPE_NONE as first item indicates just looking
2394 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002395 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2396 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002397 }
2398
Laurence Lundblade085d7952020-07-24 10:26:30 -07002399 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2400 // It is an empty bounded array or map
2401 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2402 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002403 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002404 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002405 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002406 // Nothing is ever found in an empty array or map. All items
2407 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002408 uReturn = QCBOR_SUCCESS;
2409 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002410 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002411 }
2412
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002413 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002414 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2415
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002416 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002417 UsefulInputBuf_Seek(&(pMe->InBuf),
2418 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002419
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002420 /*
2421 Loop over all the items in the map. They could be
2422 deeply nested and this should handle both definite
2423 and indefinite length maps and arrays, so this
2424 adds some complexity.
2425 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002426 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002427 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002428 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002429 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002430 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002431
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002432 /* Get the item */
2433 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002434 uReturn = QCBORDecode_GetNext(pMe, &Item);
2435 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002436 /* Got non-well-formed CBOR */
2437 goto Done;
2438 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002439
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002440 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002441 bool bMatched = false;
2442 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2443 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002444 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002445 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2446 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002447 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002448 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002449 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002450 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002451 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002452 goto Done;
2453 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002454
Laurence Lundblade1341c592020-04-11 14:19:05 -07002455 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002456 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002457 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002458 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002459 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002460 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002461 bMatched = true;
2462 }
2463 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002464
2465
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002466 if(!bMatched && pfCallback != NULL) {
2467 /*
2468 Call the callback on unmatched labels.
2469 (It is tempting to do duplicate detection here, but that would
2470 require dynamic memory allocation because the number of labels
2471 that might be encountered is unbounded.)
2472 */
2473 uReturn = (*pfCallback)(pCBContext, &Item);
2474 if(uReturn != QCBOR_SUCCESS) {
2475 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 }
2477 }
2478
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002479 /*
2480 Consume the item whether matched or not. This
2481 does the work of traversing maps and array and
2482 everything in them. In this loop only the
2483 items at the current nesting level are examined
2484 to match the labels.
2485 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002486 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2487 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002488 goto Done;
2489 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002490
2491 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002492
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002493 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494
2495 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002496 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2497 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002498
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002499 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002500 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2501
2502 Done2:
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002503 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2504 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002505 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002506 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 }
2508 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002509
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002510 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002511}
2512
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002513
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002514/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002515 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002516*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002517void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2518 int64_t nLabel,
2519 uint8_t uQcborType,
2520 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002521{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002522 if(pMe->uLastError != QCBOR_SUCCESS) {
2523 return;
2524 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002526 QCBORItem OneItemSeach[2];
2527 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2528 OneItemSeach[0].label.int64 = nLabel;
2529 OneItemSeach[0].uDataType = uQcborType;
2530 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002531
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002532 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2533 if(uReturn != QCBOR_SUCCESS) {
2534 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002536 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002537 uReturn = QCBOR_ERR_NOT_FOUND;
2538 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539 }
2540
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002541 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002542
2543 Done:
2544 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002545}
2546
2547
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002548/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002549 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002550*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002551void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2552 const char *szLabel,
2553 uint8_t uQcborType,
2554 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002555{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002556 if(pMe->uLastError != QCBOR_SUCCESS) {
2557 return;
2558 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002559
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002560 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002561 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2562 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2563 OneItemSeach[0].uDataType = uQcborType;
2564 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002565
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002566 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2567 if(uReturn != QCBOR_SUCCESS) {
2568 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002569 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002570 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002571 uReturn = QCBOR_ERR_NOT_FOUND;
2572 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002573 }
2574
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002575 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002576
2577Done:
2578 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002579}
2580
2581
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002582
2583static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2584{
2585 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2586 if(uDataType == puTypeList[i]) {
2587 return QCBOR_SUCCESS;
2588 }
2589 }
2590 return QCBOR_ERR_UNEXPECTED_TYPE;
2591}
2592
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002593/**
2594 @param[in] TagSpec Specification for matching tags.
2595 @param[in] uDataType A QCBOR data type
2596
2597 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2598 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2599
2600 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2601 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002602static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002603{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002604 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002605 // Must match the tag and only the tag
2606 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002607 }
2608
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002609 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2610 if(uReturn == QCBOR_SUCCESS) {
2611 return QCBOR_SUCCESS;
2612 }
2613
2614 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
2615 /* Must match the content type and only the content type.
2616 There was no match just above so it is a fail. */
2617 return QCBOR_ERR_UNEXPECTED_TYPE;
2618 }
2619
2620 /* If here it can match either the tag or the content
2621 and it hasn't matched the content, so the end
2622 result is whether it matches the tag. This is
2623 also the case that the CBOR standard discourages. */
2624
2625 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002626}
2627
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002628
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002629// Semi-private
2630// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002631void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2632 int64_t nLabel,
2633 TagSpecification TagSpec,
2634 QCBORItem *pItem)
2635{
2636 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2637 if(pMe->uLastError != QCBOR_SUCCESS) {
2638 return;
2639 }
2640
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002641 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002642}
2643
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002644// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002645void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2646 const char *szLabel,
2647 TagSpecification TagSpec,
2648 QCBORItem *pItem)
2649{
2650 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2651 if(pMe->uLastError != QCBOR_SUCCESS) {
2652 return;
2653 }
2654
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002655 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002656}
2657
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002658// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002659void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2660 int64_t nLabel,
2661 TagSpecification TagSpec,
2662 UsefulBufC *pString)
2663{
2664 QCBORItem Item;
2665 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2666 if(pMe->uLastError == QCBOR_SUCCESS) {
2667 *pString = Item.val.string;
2668 }
2669}
2670
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002671// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002672void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2673 const char * szLabel,
2674 TagSpecification TagSpec,
2675 UsefulBufC *pString)
2676{
2677 QCBORItem Item;
2678 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2679 if(pMe->uLastError == QCBOR_SUCCESS) {
2680 *pString = Item.val.string;
2681 }
2682}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002683
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002684/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002685 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002686*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002687QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2688{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002689 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002690}
2691
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002692/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002693 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002694*/
2695QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2696 QCBORItem *pItemList,
2697 void *pCallbackCtx,
2698 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002699{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002700 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002701}
2702
2703
Laurence Lundblade34691b92020-05-18 22:25:25 -07002704static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002706 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002707 if(pMe->uLastError != QCBOR_SUCCESS) {
2708 // Already in error state; do nothing.
2709 return;
2710 }
2711
2712 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002713 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002714 if(pMe->uLastError != QCBOR_SUCCESS) {
2715 return;
2716 }
2717
Laurence Lundblade085d7952020-07-24 10:26:30 -07002718 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2719 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2720 return;
2721 }
2722
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002723 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002724 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002725
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002726 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002727 be at the right place.
2728
2729 The UsefulInBuf offset could be anywhere, so no assumption is
2730 made about it.
2731
2732 No assumption is made about the pre-order nesting level either.
2733
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002734 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002735 the map level that is being entered.
2736 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002737 /* Seek to the data item that is the map or array */
2738 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002739
2740 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002741
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002742 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002743}
2744
2745
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002746/*
2747Public function, see header qcbor/qcbor_decode.h file
2748*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002749void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002750{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002751 QCBORItem OneItemSeach[2];
2752 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2753 OneItemSeach[0].label.int64 = nLabel;
2754 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2755 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002756
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002757 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002758 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759}
2760
2761
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002762/*
2763Public function, see header qcbor/qcbor_decode.h file
2764*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002765void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002766{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002767 QCBORItem OneItemSeach[2];
2768 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2769 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2770 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2771 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002772
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002773 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002774}
2775
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002776/*
2777Public function, see header qcbor/qcbor_decode.h file
2778*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002779void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002780{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002781 QCBORItem OneItemSeach[2];
2782 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2783 OneItemSeach[0].label.int64 = nLabel;
2784 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2785 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002786
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002787 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002788}
2789
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002790/*
2791Public function, see header qcbor/qcbor_decode.h file
2792*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002793void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2794{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002795 QCBORItem OneItemSeach[2];
2796 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2797 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2798 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2799 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002800
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002801 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002802}
2803
2804
Laurence Lundblade02625d42020-06-25 14:41:41 -07002805// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002808 QCBORError uErr;
2809
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002810 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002811 if(pMe->uLastError != QCBOR_SUCCESS) {
2812 // Already in error state; do nothing.
2813 return;
2814 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002815
2816 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002817 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002818 uErr = QCBORDecode_GetNext(pMe, &Item);
2819 if(uErr != QCBOR_SUCCESS) {
2820 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002821 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002822 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002823 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2824 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002825 }
2826
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002827 const bool bIsEmpty = (Item.uNestingLevel == Item.uNextNestLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002828 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002829 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2830 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002831 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002832 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2833 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002834 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2835 DecodeNesting_Descend(&(pMe->nesting), uType);
2836 }
2837
Laurence Lundblade02625d42020-06-25 14:41:41 -07002838 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002839
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002840 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2841 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002842
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002843Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002844 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002845}
2846
Laurence Lundblade02625d42020-06-25 14:41:41 -07002847
2848/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002849 This is the common work for exiting a level that is a bounded map, array or bstr
2850 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002851
2852 One chunk of work is to set up the pre-order traversal so it is at
2853 the item just after the bounded map, array or bstr that is being
2854 exited. This is somewhat complex.
2855
2856 The other work is to level-up the bounded mode to next higest bounded
2857 mode or the top level if there isn't one.
2858 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002859static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002860ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002861{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002862 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002863
Laurence Lundblade02625d42020-06-25 14:41:41 -07002864 /*
2865 First the pre-order-traversal byte offset is positioned to the
2866 item just after the bounded mode item that was just consumed.
2867 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002868 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2869
Laurence Lundblade02625d42020-06-25 14:41:41 -07002870 /*
2871 Next, set the current nesting level to one above the bounded level
2872 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002873
Laurence Lundblade02625d42020-06-25 14:41:41 -07002874 DecodeNesting_CheckBoundedType() is always called before this and
2875 makes sure pCurrentBounded is valid.
2876 */
2877 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2878
2879 /*
2880 This does the complex work of leveling up the pre-order traversal
2881 when the end of a map or array or another bounded level is
2882 reached. It may do nothing, or ascend all the way to the top
2883 level.
2884 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002885 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002886 if(uErr != QCBOR_SUCCESS) {
2887 goto Done;
2888 }
2889
Laurence Lundblade02625d42020-06-25 14:41:41 -07002890 /*
2891 This makes the next highest bounded level the current bounded
2892 level. If there is no next highest level, then no bounded mode is
2893 in effect.
2894 */
2895 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002896
Laurence Lundblade02625d42020-06-25 14:41:41 -07002897 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002898
2899Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002900 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002901 return uErr;
2902}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002903
Laurence Lundblade02625d42020-06-25 14:41:41 -07002904
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002905// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002906void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002907{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002908 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002909 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002910 return;
2911 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002912
Laurence Lundblade02625d42020-06-25 14:41:41 -07002913 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002914
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002915 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002916 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2917 goto Done;
2918 }
2919
Laurence Lundblade02625d42020-06-25 14:41:41 -07002920 /*
2921 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002922 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002923 from previous map search, then do a dummy search.
2924 */
2925 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002926 QCBORItem Dummy;
2927 Dummy.uLabelType = QCBOR_TYPE_NONE;
2928 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2929 if(uErr != QCBOR_SUCCESS) {
2930 goto Done;
2931 }
2932 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002933
Laurence Lundblade02625d42020-06-25 14:41:41 -07002934 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002935
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002936Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002937 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002938}
2939
2940
Laurence Lundblade1341c592020-04-11 14:19:05 -07002941void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002942{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002943 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002944 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2945 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002946}
2947
2948
Laurence Lundblade1341c592020-04-11 14:19:05 -07002949
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002950static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002951 const QCBORItem *pItem,
2952 uint8_t uTagRequirement,
2953 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002954{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002955 if(pBstr) {
2956 *pBstr = NULLUsefulBufC;
2957 }
2958
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002959 if(pMe->uLastError != QCBOR_SUCCESS) {
2960 // Already in error state; do nothing.
2961 return pMe->uLastError;
2962 }
2963
2964 QCBORError uError = QCBOR_SUCCESS;
2965
2966 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2967 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2968 goto Done;;
2969 }
2970
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002971 const TagSpecification TagSpec = {uTagRequirement,
2972 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2973 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2974 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002975
2976 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2977 if(uError != QCBOR_SUCCESS) {
2978 goto Done;
2979 }
2980
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002981 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002982 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002983 so the increment in NestLevelAscender called by ExitBoundedLevel()
2984 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002985 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002986 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002987
2988 if(pBstr) {
2989 *pBstr = pItem->val.string;
2990 }
2991
2992 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002993
2994 // Need to move UIB input cursor to the right place
2995
2996 // Really this is a subtraction and an assignment; not much code
2997 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002998 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002999
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003000 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003001
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003002 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
3003
3004 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003005
Laurence Lundblade02625d42020-06-25 14:41:41 -07003006 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
3007 uPreviousLength,
3008 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003009Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003010 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003011
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003012 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003013}
3014
3015
Laurence Lundblade02625d42020-06-25 14:41:41 -07003016/*
3017 Public function, see header qcbor/qcbor_decode.h file
3018 */
3019void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003020 uint8_t uTagRequirement,
3021 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003022{
3023 if(pMe->uLastError != QCBOR_SUCCESS) {
3024 // Already in error state; do nothing.
3025 return;
3026 }
3027
3028 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003029 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003030 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3031 if(pMe->uLastError != QCBOR_SUCCESS) {
3032 return;
3033 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003034
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003035 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003036 &Item,
3037 uTagRequirement,
3038 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003039}
3040
3041
Laurence Lundblade02625d42020-06-25 14:41:41 -07003042/*
3043 Public function, see header qcbor/qcbor_decode.h file
3044 */
3045void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
3046 uint8_t uTagRequirement,
3047 int64_t nLabel,
3048 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003049{
3050 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003051 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003052
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003053 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003054}
3055
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003056
Laurence Lundblade02625d42020-06-25 14:41:41 -07003057/*
3058 Public function, see header qcbor/qcbor_decode.h file
3059 */
3060void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3061 uint8_t uTagRequirement,
3062 const char *szLabel,
3063 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003064{
3065 QCBORItem Item;
3066 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3067
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003068 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003069}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003070
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003071
Laurence Lundblade02625d42020-06-25 14:41:41 -07003072/*
3073 Public function, see header qcbor/qcbor_decode.h file
3074 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003075void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003076{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003077 if(pMe->uLastError != QCBOR_SUCCESS) {
3078 // Already in error state; do nothing.
3079 return;
3080 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003081
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003082 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003083 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3084 return;
3085 }
3086
3087 /*
3088 Reset the length of the UsefulInputBuf to what it was before
3089 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003090 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003091 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3092 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003093
3094
Laurence Lundblade02625d42020-06-25 14:41:41 -07003095 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003096 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003097}
3098
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003099
Laurence Lundbladee6430642020-03-14 21:15:44 -07003100
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003101
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003102
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003103
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003104
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003105
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003106static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3107{
3108 switch(pItem->uDataType) {
3109 case QCBOR_TYPE_TRUE:
3110 *pBool = true;
3111 return QCBOR_SUCCESS;
3112 break;
3113
3114 case QCBOR_TYPE_FALSE:
3115 *pBool = false;
3116 return QCBOR_SUCCESS;
3117 break;
3118
3119 default:
3120 return QCBOR_ERR_UNEXPECTED_TYPE;
3121 break;
3122 }
3123}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003124
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003125/*
3126Public function, see header qcbor/qcbor_decode.h file
3127*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003128void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003129{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003130 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003131 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003132 return;
3133 }
3134
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135 QCBORError nError;
3136 QCBORItem Item;
3137
3138 nError = QCBORDecode_GetNext(pMe, &Item);
3139 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003140 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003141 return;
3142 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144}
3145
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003146/*
3147Public function, see header qcbor/qcbor_decode.h file
3148*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003149void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003150{
3151 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003152 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003153
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003154 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003155}
3156
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003157/*
3158Public function, see header qcbor/qcbor_decode.h file
3159*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003160void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3161{
3162 QCBORItem Item;
3163 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3164
3165 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3166}
3167
3168
3169
3170void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003171{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003172 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003173 // Already in error state, do nothing
3174 return;
3175 }
3176
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003177 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003178 QCBORItem Item;
3179
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003180 uError = QCBORDecode_GetNext(pMe, &Item);
3181 if(uError != QCBOR_SUCCESS) {
3182 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003183 return;
3184 }
3185
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003186 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3187
3188 if(pMe->uLastError == QCBOR_SUCCESS) {
3189 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003190 }
3191}
3192
Laurence Lundbladec4537442020-04-14 18:53:22 -07003193
3194
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003195
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003196static QCBORError ConvertBigNum(uint8_t uTagRequirement,
3197 const QCBORItem *pItem,
3198 UsefulBufC *pValue,
3199 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003200{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003201 const TagSpecification TagSpec = {uTagRequirement,
3202 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3203 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3204 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003205
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003206 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3207 if(uErr != QCBOR_SUCCESS) {
3208 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003209 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003210
3211 *pValue = pItem->val.string;
3212
3213 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3214 *pbIsNegative = false;
3215 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3216 *pbIsNegative = true;
3217 }
3218
3219 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003220}
3221
3222
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003223/**
3224 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003225 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003226void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003227{
3228 if(pMe->uLastError != QCBOR_SUCCESS) {
3229 // Already in error state, do nothing
3230 return;
3231 }
3232
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003233 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003234 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3235 if(uError != QCBOR_SUCCESS) {
3236 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003237 return;
3238 }
3239
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003240 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003241}
3242
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003243/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003244Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003245*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003246void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003247{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003248 QCBORItem Item;
3249 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003250
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003251 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003252}
3253
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003254/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003255Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003256*/
3257void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3258{
3259 QCBORItem Item;
3260 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3261
3262 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3263}
3264
3265
3266
3267// Semi private
3268QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3269{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003270
3271
3272 const TagSpecification TagSpecText = {uTagRequirement,
3273 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3274 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3275 };
3276 const TagSpecification TagSpecBinary = {uTagRequirement,
3277 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3278 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3279 };
3280
3281
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003282 QCBORError uReturn;
3283
3284 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3285 *pMessage = pItem->val.string;
3286 if(pbIsNot7Bit != NULL) {
3287 *pbIsNot7Bit = false;
3288 }
3289 uReturn = QCBOR_SUCCESS;
3290 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3291 *pMessage = pItem->val.string;
3292 if(pbIsNot7Bit != NULL) {
3293 *pbIsNot7Bit = true;
3294 }
3295 uReturn = QCBOR_SUCCESS;
3296
3297 } else {
3298 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3299 }
3300
3301 return uReturn;
3302}
3303
3304
3305
3306
3307
Laurence Lundbladec4537442020-04-14 18:53:22 -07003308
3309
3310
Laurence Lundbladee6430642020-03-14 21:15:44 -07003311
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003312typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003313
3314
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003315// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003316static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003317{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003318 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003319
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003320 if(uResult != 0) {
3321 /* This loop will run a maximum of 19 times because
3322 * UINT64_MAX < 10 ^^ 19. More than that will cause
3323 * exit with the overflow error
3324 */
3325 for(; nExponent > 0; nExponent--) {
3326 if(uResult > UINT64_MAX / 10) {
3327 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3328 }
3329 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003330 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003331
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003332 for(; nExponent < 0; nExponent++) {
3333 uResult = uResult / 10;
3334 if(uResult == 0) {
3335 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3336 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003337 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003338 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003339 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003340
3341 *puResult = uResult;
3342
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003343 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003344}
3345
3346
Laurence Lundbladee6430642020-03-14 21:15:44 -07003347/* Convert a decimal fraction to an int64_t without using
3348 floating point or math libraries. Most decimal fractions
3349 will not fit in an int64_t and this will error out with
3350 under or overflow
3351 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003352static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003353{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003354 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003355
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003356 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003357
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003358 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003359 * INT64_MAX < 2^31. More than that will cause
3360 * exist with the overflow error
3361 */
3362 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003363 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003364 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003365 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003366 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003367 nExponent--;
3368 }
3369
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003370 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003371 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3373 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003374 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003375 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003376 }
3377
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003378 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003379
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003380 return QCBOR_SUCCESS;
3381}
3382
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003383/*
3384 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3385 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003386static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3387{
3388 uint64_t uResult;
3389
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003390 // Take the absolute value of the mantissa and convert to unsigned.
3391 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003392 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3393
3394 // Do the exponentiation of the positive mantissa
3395 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3396 if(uReturn) {
3397 return uReturn;
3398 }
3399
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003400
Laurence Lundblade983500d2020-05-14 11:49:34 -07003401 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3402 of INT64_MIN. This assumes two's compliment representation where
3403 INT64_MIN is one increment farther from 0 than INT64_MAX.
3404 Trying to write -INT64_MIN doesn't work to get this because the
3405 compiler tries to work with an int64_t which can't represent
3406 -INT64_MIN.
3407 */
3408 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3409
3410 // Error out if too large
3411 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003412 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3413 }
3414
3415 // Casts are safe because of checks above
3416 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3417
3418 return QCBOR_SUCCESS;
3419}
3420
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003421/*
3422 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3423 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003424static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3425{
3426 if(nMantissa < 0) {
3427 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3428 }
3429
3430 // Cast to unsigned is OK because of check for negative
3431 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3432 // Exponentiation is straight forward
3433 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3434}
3435
3436
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003437#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003438
3439
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003440static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003441{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003442 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003444 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003445 const uint8_t *pByte = BigNum.ptr;
3446 size_t uLen = BigNum.len;
3447 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003448 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003449 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003451 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003452 }
3453
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003454 *pResult = uResult;
3455 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003456}
3457
Laurence Lundblade887add82020-05-17 05:50:34 -07003458static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003459{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003460 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003461}
3462
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003463static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003464{
3465 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003466 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3467 if(uError) {
3468 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003469 }
3470 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3471 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003472 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473}
3474
3475
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003476static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477{
3478 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003479 /* negaative int furthest from zero is INT64_MIN
3480 which is expressed as -INT64_MAX-1. The value of
3481 a negative bignum is -n-1, one further from zero
3482 than the positive bignum */
3483
3484 /* say INT64_MIN is -2; then INT64_MAX is 1.
3485 Then -n-1 <= INT64_MIN.
3486 Then -n -1 <= -INT64_MAX - 1
3487 THen n <= INT64_MAX. */
3488 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003489 if(uError) {
3490 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003491 }
3492 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003493 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003494 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003495 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003496 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003497}
3498
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003499#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003500
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003501
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003502/*
3503Convert a integers and floats to an int64_t.
3504
3505\param[in] uOptions Bit mask list of conversion options.
3506
3507\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3508
3509\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3510
3511\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3512
3513*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003514static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3515{
3516 switch(pItem->uDataType) {
3517 // TODO: float when ifdefs are set
3518 case QCBOR_TYPE_DOUBLE:
3519 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3520 // TODO: what about under/overflow here?
3521 // Invokes the floating-point HW and/or compiler-added libraries
3522 feclearexcept(FE_ALL_EXCEPT);
3523 *pnValue = llround(pItem->val.dfnum);
3524 if(fetestexcept(FE_INVALID)) {
3525 // TODO: better error code
3526 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3527 }
3528 } else {
3529 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3530 }
3531 break;
3532
3533 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003534 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003535 *pnValue = pItem->val.int64;
3536 } else {
3537 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3538 }
3539 break;
3540
3541 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003542 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003543 if(pItem->val.uint64 < INT64_MAX) {
3544 *pnValue = pItem->val.int64;
3545 } else {
3546 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3547 }
3548 } else {
3549 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3550 }
3551 break;
3552
3553 default:
3554 return QCBOR_ERR_UNEXPECTED_TYPE;
3555 }
3556 return QCBOR_SUCCESS;
3557}
3558
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003559
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003560void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3561 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003562 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003563 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003564{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003565 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003566 return;
3567 }
3568
Laurence Lundbladee6430642020-03-14 21:15:44 -07003569 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003570 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3571 if(uError) {
3572 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003573 return;
3574 }
3575
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003576 if(pItem) {
3577 *pItem = Item;
3578 }
3579
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003580 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003581}
3582
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003583
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003584void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3585 int64_t nLabel,
3586 uint32_t uOptions,
3587 int64_t *pnValue,
3588 QCBORItem *pItem)
3589{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003590 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003591 if(pMe->uLastError != QCBOR_SUCCESS) {
3592 return;
3593 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003594
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003595 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003596}
3597
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003598
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003599void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3600 const char * szLabel,
3601 uint32_t uOptions,
3602 int64_t *pnValue,
3603 QCBORItem *pItem)
3604{
3605 if(pMe->uLastError != QCBOR_SUCCESS) {
3606 return;
3607 }
3608
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003609 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003610 if(pMe->uLastError != QCBOR_SUCCESS) {
3611 return;
3612 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003613
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003614 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003615}
3616
3617
3618
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003619/*
3620 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003621
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003622 \param[in] uOptions Bit mask list of conversion options.
3623
3624 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3625
3626 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3627
3628 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3629
3630 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3632{
3633 QCBORError uErr;
3634
3635 switch(pItem->uDataType) {
3636
3637 case QCBOR_TYPE_POSBIGNUM:
3638 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3639 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003640 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003641 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003642 }
3643 break;
3644
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003645 case QCBOR_TYPE_NEGBIGNUM:
3646 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3647 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003648 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003650 }
3651 break;
3652
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3654 case QCBOR_TYPE_DECIMAL_FRACTION:
3655 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3656 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3657 pItem->val.expAndMantissa.nExponent,
3658 pnValue,
3659 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003660 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003661 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3662 }
3663 break;
3664
3665 case QCBOR_TYPE_BIGFLOAT:
3666 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3667 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3668 pItem->val.expAndMantissa.nExponent,
3669 pnValue,
3670 Exponentitate2);
3671 } else {
3672 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3673 }
3674 break;
3675
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003676 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3677 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3678 int64_t nMantissa;
3679 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3680 if(uErr) {
3681 return uErr;
3682 }
3683 return ExponentiateNN(nMantissa,
3684 pItem->val.expAndMantissa.nExponent,
3685 pnValue,
3686 Exponentitate10);
3687 } else {
3688 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3689 }
3690 break;
3691
3692 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3693 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3694 int64_t nMantissa;
3695 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3696 if(uErr) {
3697 return uErr;
3698 }
3699 return ExponentiateNN(nMantissa,
3700 pItem->val.expAndMantissa.nExponent,
3701 pnValue,
3702 Exponentitate10);
3703 } else {
3704 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3705 }
3706 break;
3707
3708 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3709 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3710 int64_t nMantissa;
3711 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3712 if(uErr) {
3713 return uErr;
3714 }
3715 return ExponentiateNN(nMantissa,
3716 pItem->val.expAndMantissa.nExponent,
3717 pnValue,
3718 Exponentitate2);
3719 } else {
3720 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3721 }
3722 break;
3723
3724 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3725 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3726 int64_t nMantissa;
3727 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3728 if(uErr) {
3729 return uErr;
3730 }
3731 return ExponentiateNN(nMantissa,
3732 pItem->val.expAndMantissa.nExponent,
3733 pnValue,
3734 Exponentitate2);
3735 } else {
3736 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 }
3738 break;
3739
Laurence Lundbladec4537442020-04-14 18:53:22 -07003740 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003741 return QCBOR_ERR_UNEXPECTED_TYPE;
3742#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003743 }
3744}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003745
3746
Laurence Lundbladec4537442020-04-14 18:53:22 -07003747/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003748 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003749 */
3750void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003751{
3752 QCBORItem Item;
3753
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003754 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003755
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003756 if(pMe->uLastError == QCBOR_SUCCESS) {
3757 // The above conversion succeeded
3758 return;
3759 }
3760
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003761 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003762 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003763 return;
3764 }
3765
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003766 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003767}
3768
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003769
3770/*
3771Public function, see header qcbor/qcbor_decode.h file
3772*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003773void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3774{
3775 QCBORItem Item;
3776
3777 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3778
3779 if(pMe->uLastError == QCBOR_SUCCESS) {
3780 // The above conversion succeeded
3781 return;
3782 }
3783
3784 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3785 // The above conversion failed in a way that code below can't correct
3786 return;
3787 }
3788
3789 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3790}
3791
3792
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003793/*
3794Public function, see header qcbor/qcbor_decode.h file
3795*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003796void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3797{
3798 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003799 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3800
3801 if(pMe->uLastError == QCBOR_SUCCESS) {
3802 // The above conversion succeeded
3803 return;
3804 }
3805
3806 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3807 // The above conversion failed in a way that code below can't correct
3808 return;
3809 }
3810
3811 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3812}
3813
3814
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003815static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3816{
3817 switch(pItem->uDataType) {
3818 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003819 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003820 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3821 feclearexcept(FE_ALL_EXCEPT);
3822 double dRounded = round(pItem->val.dfnum);
3823 // TODO: over/underflow
3824 if(fetestexcept(FE_INVALID)) {
3825 // TODO: better error code
3826 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3827 } else if(isnan(dRounded)) {
3828 // TODO: better error code
3829 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3830 } else if(dRounded >= 0) {
3831 *puValue = (uint64_t)dRounded;
3832 } else {
3833 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3834 }
3835 } else {
3836 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3837 }
3838 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003839
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003840 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003841 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003842 if(pItem->val.int64 >= 0) {
3843 *puValue = (uint64_t)pItem->val.int64;
3844 } else {
3845 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3846 }
3847 } else {
3848 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3849 }
3850 break;
3851
3852 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003853 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003854 *puValue = pItem->val.uint64;
3855 } else {
3856 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3857 }
3858 break;
3859
3860 default:
3861 return QCBOR_ERR_UNEXPECTED_TYPE;
3862 }
3863 return QCBOR_SUCCESS;
3864}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003865
3866
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003867void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3868 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003869 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003870 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003871{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003872 if(pMe->uLastError != QCBOR_SUCCESS) {
3873 return;
3874 }
3875
Laurence Lundbladec4537442020-04-14 18:53:22 -07003876 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003877
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003878 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3879 if(uError) {
3880 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003881 return;
3882 }
3883
Laurence Lundbladea826c502020-05-10 21:07:00 -07003884 if(pItem) {
3885 *pItem = Item;
3886 }
3887
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003888 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003889}
3890
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003891
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003892void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3893{
3894 int64_t uValue;
3895 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3896 if(pMe->uLastError != QCBOR_SUCCESS) {
3897 return;
3898 }
3899
3900 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3901 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3902 }
3903}
3904
3905void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3906{
3907 int64_t uValue;
3908 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3909 if(pMe->uLastError != QCBOR_SUCCESS) {
3910 return;
3911 }
3912
3913 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3914 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3915 }
3916}
3917
3918void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3919{
3920 int64_t uValue;
3921 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3922 if(pMe->uLastError != QCBOR_SUCCESS) {
3923 return;
3924 }
3925
3926 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3927 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3928 }
3929}
3930
3931
3932
3933
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003934void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3935 int64_t nLabel,
3936 uint32_t uOptions,
3937 uint64_t *puValue,
3938 QCBORItem *pItem)
3939{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003940 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003941 if(pMe->uLastError != QCBOR_SUCCESS) {
3942 return;
3943 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003944
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003945 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003946}
3947
3948
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003949void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003950 const char * szLabel,
3951 uint32_t uOptions,
3952 uint64_t *puValue,
3953 QCBORItem *pItem)
3954{
3955 if(pMe->uLastError != QCBOR_SUCCESS) {
3956 return;
3957 }
3958
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003959 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003960 if(pMe->uLastError != QCBOR_SUCCESS) {
3961 return;
3962 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003963
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003964 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003965}
3966
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003967/*
3968 Public function, see header qcbor/qcbor_decode.h file
3969*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003970static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3971{
3972 QCBORError uErr;
3973
3974 switch(pItem->uDataType) {
3975
3976 case QCBOR_TYPE_POSBIGNUM:
3977 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3978 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3979 } else {
3980 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3981 }
3982 break;
3983
3984 case QCBOR_TYPE_NEGBIGNUM:
3985 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3986 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3987 } else {
3988 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3989 }
3990 break;
3991
3992#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3993
3994 case QCBOR_TYPE_DECIMAL_FRACTION:
3995 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3996 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3997 pItem->val.expAndMantissa.nExponent,
3998 puValue,
3999 Exponentitate10);
4000 } else {
4001 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4002 }
4003 break;
4004
4005 case QCBOR_TYPE_BIGFLOAT:
4006 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4007 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4008 pItem->val.expAndMantissa.nExponent,
4009 puValue,
4010 Exponentitate2);
4011 } else {
4012 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4013 }
4014 break;
4015
4016 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4017 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4018 // TODO: Would be better to convert to unsigned
4019 int64_t nMantissa;
4020 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4021 if(uErr != QCBOR_SUCCESS) {
4022 return uErr;
4023 }
4024 return ExponentitateNU(nMantissa,
4025 pItem->val.expAndMantissa.nExponent,
4026 puValue,
4027 Exponentitate10);
4028 } else {
4029 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4030 }
4031 break;
4032
4033 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4034 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4035 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4036 } else {
4037 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4038 }
4039 break;
4040
4041 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4042 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4043 // TODO: Would be better to convert to unsigned
4044 int64_t nMantissa;
4045 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4046 if(uErr != QCBOR_SUCCESS) {
4047 return uErr;
4048 }
4049 return ExponentitateNU(nMantissa,
4050 pItem->val.expAndMantissa.nExponent,
4051 puValue,
4052 Exponentitate2);
4053 } else {
4054 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4055 }
4056 break;
4057
4058 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4059 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4060 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4061 } else {
4062 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4063 }
4064 break;
4065#endif
4066 default:
4067 return QCBOR_ERR_UNEXPECTED_TYPE;
4068 }
4069}
4070
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004071/*
4072 Public function, see header qcbor/qcbor_decode.h file
4073*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004074void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004075{
4076 QCBORItem Item;
4077
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004078 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004079
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004080 if(pMe->uLastError == QCBOR_SUCCESS) {
4081 // The above conversion succeeded
4082 return;
4083 }
4084
4085 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4086 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004087 return;
4088 }
4089
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004090 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004091}
4092
Laurence Lundbladec4537442020-04-14 18:53:22 -07004093
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004094/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004095 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004096*/
4097void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4098{
4099 QCBORItem Item;
4100
4101 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4102
4103 if(pMe->uLastError == QCBOR_SUCCESS) {
4104 // The above conversion succeeded
4105 return;
4106 }
4107
4108 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4109 // The above conversion failed in a way that code below can't correct
4110 return;
4111 }
4112
4113 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4114}
4115
4116
4117/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004118 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004119*/
4120void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4121{
4122 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004123 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004124
4125 if(pMe->uLastError == QCBOR_SUCCESS) {
4126 // The above conversion succeeded
4127 return;
4128 }
4129
4130 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4131 // The above conversion failed in a way that code below can't correct
4132 return;
4133 }
4134
4135 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4136}
4137
4138
4139static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4140{
4141 switch(pItem->uDataType) {
4142 // TODO: float when ifdefs are set
4143 case QCBOR_TYPE_DOUBLE:
4144 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4145 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4146 *pdValue = pItem->val.dfnum;
4147 } else {
4148 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4149 }
4150 }
4151 break;
4152
4153 case QCBOR_TYPE_INT64:
4154 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4155 // TODO: how does this work?
4156 *pdValue = (double)pItem->val.int64;
4157
4158 } else {
4159 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4160 }
4161 break;
4162
4163 case QCBOR_TYPE_UINT64:
4164 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4165 *pdValue = (double)pItem->val.uint64;
4166 } else {
4167 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4168 }
4169 break;
4170
4171 default:
4172 return QCBOR_ERR_UNEXPECTED_TYPE;
4173 }
4174
4175 return QCBOR_SUCCESS;
4176}
4177
4178
4179
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004180void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4181 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004182 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004183 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004184{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004185 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004186 return;
4187 }
4188
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004189 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004190
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004191 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004192 if(uError) {
4193 pMe->uLastError = (uint8_t)uError;
4194 return;
4195 }
4196
4197 if(pItem) {
4198 *pItem = Item;
4199 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004200
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004201 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004202}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004203
Laurence Lundbladec4537442020-04-14 18:53:22 -07004204
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004205void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4206 int64_t nLabel,
4207 uint32_t uOptions,
4208 double *pdValue,
4209 QCBORItem *pItem)
4210{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004211 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004212 if(pMe->uLastError != QCBOR_SUCCESS) {
4213 return;
4214 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004215
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004216 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217}
4218
4219void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4220 const char * szLabel,
4221 uint32_t uOptions,
4222 double *pdValue,
4223 QCBORItem *pItem)
4224{
4225 if(pMe->uLastError != QCBOR_SUCCESS) {
4226 return;
4227 }
4228
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004229 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004230 if(pMe->uLastError != QCBOR_SUCCESS) {
4231 return;
4232 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004234 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004235}
4236
4237
4238
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004239static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4240{
4241 double dResult;
4242
4243 dResult = 0.0;
4244 const uint8_t *pByte = BigNum.ptr;
4245 size_t uLen = BigNum.len;
4246 /* This will overflow and become the float value INFINITY if the number
4247 is too large to fit. No error will be logged.
4248 TODO: should an error be logged? */
4249 while(uLen--) {
4250 dResult = (dResult * 256.0) + (double)*pByte++;
4251 }
4252
4253 return dResult;
4254}
4255
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004256static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004257{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004258 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004259 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4260
4261 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004262 switch(pItem->uDataType) {
4263 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004264
4265#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004266 case QCBOR_TYPE_DECIMAL_FRACTION:
4267 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4268 // TODO: rounding and overflow errors
4269 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4270 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4271 } else {
4272 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4273 }
4274 break;
4275
4276 case QCBOR_TYPE_BIGFLOAT:
4277 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4278 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4279 exp2((double)pItem->val.expAndMantissa.nExponent);
4280 } else {
4281 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4282 }
4283 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004284#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004285
4286 case QCBOR_TYPE_POSBIGNUM:
4287 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4288 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4289 } else {
4290 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4291 }
4292 break;
4293
4294 case QCBOR_TYPE_NEGBIGNUM:
4295 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004296 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004297 } else {
4298 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4299 }
4300 break;
4301
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004302#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004303 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4304 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4305 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4306 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4307 } else {
4308 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4309 }
4310 break;
4311
4312 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4313 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4314 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4315 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4316 } else {
4317 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4318 }
4319 break;
4320
4321 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4322 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4323 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4324 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4325 } else {
4326 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4327 }
4328 break;
4329
4330 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4331 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004332 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004333 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4334 } else {
4335 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4336 }
4337 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004338#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4339
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004340
4341 default:
4342 return QCBOR_ERR_UNEXPECTED_TYPE;
4343 }
4344
4345 return QCBOR_SUCCESS;
4346}
4347
4348
4349/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004350 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004351*/
4352void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4353{
4354
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004355 QCBORItem Item;
4356
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004358
4359 if(pMe->uLastError == QCBOR_SUCCESS) {
4360 // The above conversion succeeded
4361 return;
4362 }
4363
4364 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4365 // The above conversion failed in a way that code below can't correct
4366 return;
4367 }
4368
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004369 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004370}
4371
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372
4373/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004374 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004375*/
4376void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4377{
4378 QCBORItem Item;
4379
4380 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4381
4382 if(pMe->uLastError == QCBOR_SUCCESS) {
4383 // The above conversion succeeded
4384 return;
4385 }
4386
4387 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4388 // The above conversion failed in a way that code below can't correct
4389 return;
4390 }
4391
4392 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4393}
4394
4395
4396/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004397 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004398*/
4399void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4400{
4401 QCBORItem Item;
4402 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4403
4404 if(pMe->uLastError == QCBOR_SUCCESS) {
4405 // The above conversion succeeded
4406 return;
4407 }
4408
4409 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4410 // The above conversion failed in a way that code below can't correct
4411 return;
4412 }
4413
4414 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4415}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004416
4417
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004418#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004419static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
4420 uint8_t uTagRequirement,
4421 QCBORItem *pItem,
4422 int64_t *pnMantissa,
4423 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004424{
4425 QCBORError uErr;
4426
4427 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004428
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004429 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4430 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4431 return;
4432 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004433 /* The decimal fraction was untagged so it shows up as an
4434 array at this point. We are called to interpret it
4435 as a decimal fraction, so do protocol decoding. If
4436 it was tagged, iw would shouw up here with the
4437 QCBOR_TYPE_DECIMAL_FRACTION or such. */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004438 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4439 if(uErr != QCBOR_SUCCESS) {
4440 pMe->uLastError = (uint8_t)uErr;
4441 return;
4442 }
4443 }
4444
4445 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4446 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4447 return;
4448 }
4449
4450 switch (pItem->uDataType) {
4451
4452 case QCBOR_TYPE_DECIMAL_FRACTION:
4453 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4454 *pnExponent = pItem->val.expAndMantissa.nExponent;
4455 break;
4456
4457 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4458 *pnExponent = pItem->val.expAndMantissa.nExponent;
4459
4460 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4461 if(uErr != QCBOR_SUCCESS) {
4462 pMe->uLastError = (uint8_t)uErr;
4463 }
4464 break;
4465
4466 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4467 *pnExponent = pItem->val.expAndMantissa.nExponent;
4468
4469 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4470 if(uErr != QCBOR_SUCCESS) {
4471 pMe->uLastError = (uint8_t)uErr;
4472 }
4473 break;
4474
4475 default:
4476 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4477 }
4478}
4479
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004480
4481void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4482 uint8_t uTagRequirement,
4483 int64_t *pnMantissa,
4484 int64_t *pnExponent)
4485{
4486 if(pMe->uLastError != QCBOR_SUCCESS) {
4487 return;
4488 }
4489
4490 QCBORItem Item;
4491 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4492 if(uError) {
4493 pMe->uLastError = (uint8_t)uError;
4494 return;
4495 }
4496
4497 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4498}
4499
4500
4501void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004502 uint8_t uTagRequirement,
4503 int64_t nLabel,
4504 int64_t *pnMantissa,
4505 int64_t *pnExponent)
4506{
4507 QCBORItem Item;
4508
4509 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004510 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004511}
4512
4513
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004514void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
4515 uint8_t uTagRequirement,
4516 const char *szLabel,
4517 int64_t *pnMantissa,
4518 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004519{
4520 QCBORItem Item;
4521
4522 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4523
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004524 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004525}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004526#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004527
4528
4529UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4530{
4531 while(uInt & 0xff0000000000UL) {
4532 uInt = uInt << 8;
4533 };
4534
4535 UsefulOutBuf UOB;
4536
4537 UsefulOutBuf_Init(&UOB, Buffer);
4538
4539 while(uInt) {
4540 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4541 uInt = uInt << 8;
4542 }
4543
4544 return UsefulOutBuf_OutUBuf(&UOB);
4545}
4546
4547
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004548#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4549
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004550static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
4551 uint8_t uTagRequirement,
4552 QCBORItem *pItem,
4553 UsefulBuf BufferForMantissa,
4554 UsefulBufC *pMantissa,
4555 bool *pbIsNegative,
4556 int64_t *pnExponent)
4557{
4558
4559 const TagSpecification TagSpec = {uTagRequirement,
4560 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4561 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4562 };
4563
4564 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4565 if(uErr != QCBOR_SUCCESS) {
4566 pMe->uLastError = (uint8_t)uErr;
4567 return;
4568 }
4569
4570 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4571 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4572 if(uErr != QCBOR_SUCCESS) {
4573 pMe->uLastError = (uint8_t)uErr;
4574 return;
4575 }
4576 }
4577
4578 uint64_t uMantissa;
4579
4580 switch (pItem->uDataType) {
4581
4582 case QCBOR_TYPE_DECIMAL_FRACTION:
4583 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4584 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4585 *pbIsNegative = false;
4586 } else {
4587 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4588 *pbIsNegative = true;
4589 }
4590 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4591 *pnExponent = pItem->val.expAndMantissa.nExponent;
4592 break;
4593
4594 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4595 *pnExponent = pItem->val.expAndMantissa.nExponent;
4596 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4597 *pbIsNegative = false;
4598 break;
4599
4600 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4601 *pnExponent = pItem->val.expAndMantissa.nExponent;
4602 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4603 *pbIsNegative = true;
4604 break;
4605
4606 default:
4607 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4608 }
4609}
4610
4611
4612void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4613 uint8_t uTagRequirement,
4614 UsefulBuf MantissaBuffer,
4615 UsefulBufC *pMantissa,
4616 bool *pbMantissaIsNegative,
4617 int64_t *pnExponent)
4618{
4619
4620 if(pMe->uLastError != QCBOR_SUCCESS) {
4621 return;
4622 }
4623
4624 QCBORItem Item;
4625 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4626 if(uError) {
4627 pMe->uLastError = (uint8_t)uError;
4628 return;
4629 }
4630
4631 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4632
4633}
4634
4635void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
4636 uint8_t uTagRequirement,
4637 int64_t nLabel,
4638 UsefulBuf BufferForMantissa,
4639 UsefulBufC *pMantissa,
4640 bool *pbIsNegative,
4641 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004642{
4643 QCBORItem Item;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004644
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004645 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004646 if(pMe->uLastError != QCBOR_SUCCESS) {
4647 return;
4648 }
4649
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004650 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4651}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004652
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004653
4654void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
4655 uint8_t uTagRequirement,
4656 const char *szLabel,
4657 UsefulBuf BufferForMantissa,
4658 UsefulBufC *pMantissa,
4659 bool *pbIsNegative,
4660 int64_t *pnExponent)
4661{
4662 QCBORItem Item;
4663
4664 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4665 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004666 return;
4667 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004668
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004669 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004670}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004671
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004672#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004673
4674/*
4675
4676 TODO: do something with this text
4677 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4678 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4679 is the byte offset in the encoded input and a leaf counter for definite
4680 length maps and arrays. Indefinite length maps and arrays are handled
4681 by look ahead for the break.
4682
4683 The view presented to the caller has tags, labels and the chunks of
4684 indefinite length strings aggregated into one decorated data item.
4685
4686 The caller understands the nesting level in pre-order traversal by
4687 the fact that a data item that is a map or array is presented to
4688 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4689 and the nesting level of the next item.
4690
4691 The caller traverse maps and arrays in a special mode that often more convenient
4692 that tracking by nesting level. When an array or map is expected or encountered
4693 the EnterMap or EnteryArray can be called.
4694
4695 When entering a map or array like this, the cursor points to the first
4696 item in the map or array. When exiting, it points to the item after
4697 the map or array, regardless of whether the items in the map or array were
4698 all traversed.
4699
4700 When in a map or array, the cursor functions as normal, but traversal
4701 cannot go past the end of the map or array that was entered. If this
4702 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4703 go past the end of the map or array ExitMap() or ExitArray() must
4704 be called. It can be called any time regardless of the position
4705 of the cursor.
4706
4707 When a map is entered, a special function allows fetching data items
4708 by label. This call will traversal the whole map looking for the
4709 labeled item. The whole map is traversed so as to detect duplicates.
4710 This type of fetching items does not affect the normal traversal
4711 cursor.
4712
4713
4714 When a data item is presented to the caller, the nesting level of the data
4715 item is presented along with the nesting level of the item that would be
4716 next consumed.
4717 */