blob: 515f58ff1ab3fe3f14ea820c8584d9661520cf6c [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 Lundblade02625d42020-06-25 14:41:41 -070084 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080085
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 See qcbor/qcbor_private.h for definition of the object
87 described here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080088 ===========================================================================*/
89
Laurence Lundblade9c905e82020-04-25 11:31:38 -070090/*
91The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
92formed by intermediate nodes (arrays and maps). The cursor for the traversal
93 is the byte offset in the encoded input and a leaf counter for definite
94 length maps and arrays. Indefinite length maps and arrays are handled
95 by look ahead for the break.
96
97 The view presented to the caller has tags, labels and the chunks of
98 indefinite length strings aggregated into one decorated data item.
99
100The caller understands the nesting level in pre-order traversal by
101 the fact that a data item that is a map or array is presented to
102 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
103 and the nesting level of the next item.
104
105 The caller traverse maps and arrays in a special mode that often more convenient
106 that tracking by nesting level. When an array or map is expected or encountered
107 the EnterMap or EnteryArray can be called.
108
109 When entering a map or array like this, the cursor points to the first
110 item in the map or array. When exiting, it points to the item after
111 the map or array, regardless of whether the items in the map or array were
112 all traversed.
113
114 When in a map or array, the cursor functions as normal, but traversal
115 cannot go past the end of the map or array that was entered. If this
116 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
117 go past the end of the map or array ExitMap() or ExitArray() must
118 be called. It can be called any time regardless of the position
119 of the cursor.
120
121 When a map is entered, a special function allows fetching data items
122 by label. This call will traversal the whole map looking for the
123 labeled item. The whole map is traversed so as to detect duplicates.
124 This type of fetching items does not affect the normal traversal
125 cursor.
126
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127
128When a data item is presented to the caller, the nesting level of the data
129 item is presented along with the nesting level of the item that would be
130 next consumed.
131
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700132 */
133
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700134
135inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700136DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700137{
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700138 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700139 /*
140 Limit in DecodeNesting_Descend against more than
141 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
142 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700143 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700144}
145
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700146
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147inline static uint8_t
148DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700149{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700150 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700151 /*
152 Limit in DecodeNesting_Descend against more than
153 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
154 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700156}
157
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700158
Laurence Lundblade02625d42020-06-25 14:41:41 -0700159static inline size_t
160DecodeNesting_GetMapOrArrayStart(QCBORDecodeNesting *pNesting)
161{
162 return pNesting->pCurrentBounded->u.ma.uStartOffset;
163}
164
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700165
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700166inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700169 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
170 return true;
171 } else {
172 return false;
173 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700177inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700179{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
181 /* Not a map or array */
182 return false;
183 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700184 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185 /* Not indefinte length */
186 return false;
187 }
188 /* All checks passed; is an indefinte length map or array */
189 return true;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193inline static bool
194DecodeNesting_IsDefiniteLength(const QCBORDecodeNesting *pNesting)
195{
196 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
197 /* Not a map or array */
198 return false;
199 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700200 if(pNesting->pCurrent->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201 /* Is indefinite */
202 return false;
203 }
204 /* All checks passed; is a definte length map or array */
205 return true;
206}
207
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700208
Laurence Lundblade642282a2020-06-23 12:00:33 -0700209inline static bool
210DecodeNesting_IsBstrWrapped(const QCBORDecodeNesting *pNesting)
211{
212 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
213 /* is a byte string */
214 return true;
215 }
216 return false;
217}
218
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700219
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700220inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700221{
222 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
223 return true;
224 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700225 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700226 return true;
227 }
228 return false;
229}
230
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700231
Laurence Lundblade02625d42020-06-25 14:41:41 -0700232inline static void DecodeNesting_SetMapOrArrayBoundedMode(const QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700233{
234 // Should be only called on maps and arrays
235 // TODO: check this cast, maybe give an error?
236 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
237}
238
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700239
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240inline static void DecodeNesting_ClearBoundedMode(const QCBORDecodeNesting *pNesting)
241{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700242 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243}
244
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700245
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700246inline static bool
Laurence Lundblade642282a2020-06-23 12:00:33 -0700247DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700248{
249 if(pNesting->pCurrentBounded == NULL) {
250 /* No bounded map or array or... set up. */
251 return false;
252 }
253 if(pNesting->pCurrentBounded->uLevelType == QCBOR_TYPE_BYTE_STRING) {
254 /* Not a map or array */
255 return false;
256 }
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700257 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 /* Not in bounded mode. */
259 return false;
260 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700261 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 /* An indefinite length map or array */
263 return false;
264 }
265 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
266 /* Count is not zero, still unconsumed items. */
267 return false;
268 }
269 /* All checks passed, got to the end of a definite length map or array */
270 return true;
271}
272
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700273
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700274inline static bool
275DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
276{
277 /* Must only be called on map / array; TODO: add checks? */
278 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
279 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700280 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700281 return false;
282 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700283}
284
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700285
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700286inline static bool
287DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700288{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700289 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
290 return true;
291 } else {
292 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700293 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700294}
295
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700296
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700297inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700299{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700301 return false;
302 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303
304 if(pNesting->pCurrentBounded->uLevelType != uType) {
305 return false;
306 }
307
308 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700309}
310
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700312inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700313DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700314{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700315 /* Only call on array / map; TODO: add check?*/
316 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700317}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700318
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700319
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700320inline static void
321DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
322{
323 pNesting->pCurrent--;
324}
325
Laurence Lundblade02625d42020-06-25 14:41:41 -0700326
327static QCBORError
328DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
329{
330 // Error out if nesting is too deep
331 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
332 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
333 }
334
335 // The actual descend
336 pNesting->pCurrent++;
337
338 pNesting->pCurrent->uLevelType = uType;
339
340 return QCBOR_SUCCESS;
341}
342
343
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700344inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700345DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700346{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700347 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
348 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700349 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700350}
351
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700352
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700353inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700354DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700355 uint8_t uQCBORType,
356 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700358 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700359
360 if(uCount == 0) {
361 // Nothing to do for empty definite lenth arrays. They are just are
362 // effectively the same as an item that is not a map or array
363 goto Done;
364 // Empty indefinite length maps and arrays are handled elsewhere
365 }
366
367 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700368 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
369 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
370 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700371 goto Done;
372 }
373
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
375 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700376 goto Done;
377 }
378
Laurence Lundblade02625d42020-06-25 14:41:41 -0700379 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700380 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
381 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700382
383 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700384
385Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700386 return uError;;
387}
388
389
390static inline void
391DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
392{
393 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
394}
395
396
397static inline void
398DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
399{
400 while(pNesting->pCurrentBounded != &(pNesting->pMapsAndArrays[0])) {
401 pNesting->pCurrentBounded--;
402 if(DecodeNesting_IsCurrentBounded(pNesting)) {
403 break;
404 }
405 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700406}
407
408
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700409inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700410DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
411 size_t uEndOffset,
412 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
417 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418 goto Done;
419 }
420
Laurence Lundblade02625d42020-06-25 14:41:41 -0700421 // Fill in the new byte string level
422 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700423 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700425
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427 pNesting->pCurrentBounded = pNesting->pCurrent;
428
429Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430 return uError;;
431}
432
433
434static inline void
435DecodeNesting_ZeroDefiniteLengthCount(QCBORDecodeNesting *pNesting)
436{
437 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438}
439
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700440
Laurence Lundbladeee851742020-01-08 08:37:05 -0800441inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700442DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700443{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700445 pNesting->pMapsAndArrays[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700446 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
447}
448
449
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700450inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700452{
453 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700454 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700455
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700456 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700457 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700458 }
459}
460
Laurence Lundblade02625d42020-06-25 14:41:41 -0700461static inline void
462DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700463{
464 *pNesting = *pSave;
465}
466
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700467
Laurence Lundblade02625d42020-06-25 14:41:41 -0700468static inline uint32_t
469DecodeNesting_GetEndOfBstr(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700470{
471 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
472}
473
474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475static inline uint32_t
476DecodeNesting_GetPreviousBoundedEnd(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700477{
478 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
479}
480
481
Laurence Lundblade02625d42020-06-25 14:41:41 -0700482#include <stdio.h>
483void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700484{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 printf("---%s--%d--%d--\narrow is current bounded level\nLevel Count Type S-Offset SaveCount Bounded E-Offset\n",
486 szName,
487 (uint32_t)pBuf->cursor,
488 (uint32_t)pBuf->UB.len);
489 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
490 if(&(pNesting->pMapsAndArrays[i]) > pNesting->pCurrent) {
491 break;
492 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700493
Laurence Lundblade02625d42020-06-25 14:41:41 -0700494 // TODO: print different for BS and MA
495 printf("%2s %2d %5d %s %6u %5d %d %5d\n",
496 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
497 i,
498 pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
499 pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_MAP ? "map " :
500 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_ARRAY ? "array" :
501 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
502 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_NONE ? "none " : "?????"))),
503 pNesting->pMapsAndArrays[i].u.ma.uStartOffset,
504 pNesting->pMapsAndArrays[i].u.ma.uCountTotal,
505 0, // TODO: fix this
506 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset
507 );
508
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700509 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700510 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700511}
512
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700513
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700514
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800516 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
517
518 The following four functions are pretty wrappers for invocation of
519 the string allocator supplied by the caller.
520
Laurence Lundbladeee851742020-01-08 08:37:05 -0800521 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800522
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523static inline void
524StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529// StringAllocator_Reallocate called with pMem NULL is
530// equal to StringAllocator_Allocate()
531static inline UsefulBuf
532StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
533 void *pMem,
534 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800535{
536 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
537}
538
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539static inline UsefulBuf
540StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800541{
542 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
543}
544
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545static inline void
546StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800547{
548 if(pMe->pfAllocator) {
549 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
550 }
551}
552
553
554
Laurence Lundbladeee851742020-01-08 08:37:05 -0800555/*===========================================================================
556 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800558 See qcbor/qcbor_decode.h for definition of the object
559 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561/*
562 Public function, see header file
563 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800564void QCBORDecode_Init(QCBORDecodeContext *me,
565 UsefulBufC EncodedCBOR,
566 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567{
568 memset(me, 0, sizeof(QCBORDecodeContext));
569 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570 // Don't bother with error check on decode mode. If a bad value is
571 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700572 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700573 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700574 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700575 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700576 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700577}
578
579
580/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581 Public function, see header file
582 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
584 QCBORStringAllocate pfAllocateFunction,
585 void *pAllocateContext,
586 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700587{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800588 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
589 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
590 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700591}
592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593
594/*
595 Public function, see header file
596 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
598 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700599{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700600 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601}
602
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700603
604/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800605 This decodes the fundamental part of a CBOR data item, the type and
606 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800607
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700608 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladeee851742020-01-08 08:37:05 -0800610 This does the network->host byte order conversion. The conversion
611 here also results in the conversion for floats in addition to that
612 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800613
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700614 This returns:
615 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800616
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800617 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800618 tags and floats and length for strings and arrays
619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800621 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800622
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800623 The int type is preferred to uint8_t for some variables as this
624 avoids integer promotions, can reduce code size and makes
625 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800627inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
628 int *pnMajorType,
629 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800630 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700632 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800635 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800636
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 const int nTmpMajorType = nInitialByte >> 5;
639 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800641 // Where the number or argument accumulates
642 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800644 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700645 // Need to get 1,2,4 or 8 additional argument bytes. Map
646 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800647 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800648
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800649 // Loop getting all the bytes in the argument
650 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800651 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800652 // This shift and add gives the endian conversion
653 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
654 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800655 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800656 // The reserved and thus-far unused additional info values
657 nReturn = QCBOR_ERR_UNSUPPORTED;
658 goto Done;
659 } else {
660 // Less than 24, additional info is argument or 31, an indefinite length
661 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800662 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800664
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 if(UsefulInputBuf_GetError(pUInBuf)) {
666 nReturn = QCBOR_ERR_HIT_END;
667 goto Done;
668 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670 // All successful if we got here.
671 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800672 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800673 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800675
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676Done:
677 return nReturn;
678}
679
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800682 CBOR doesn't explicitly specify two's compliment for integers but all
683 CPUs use it these days and the test vectors in the RFC are so. All
684 integers in the CBOR structure are positive and the major type
685 indicates positive or negative. CBOR can express positive integers
686 up to 2^x - 1 where x is the number of bits and negative integers
687 down to 2^x. Note that negative numbers can be one more away from
688 zero than positive. Stdint, as far as I can tell, uses two's
689 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800692 used carefully here, and in particular why it isn't used in the interface.
693 Also see
694 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
695
696 Int is used for values that need less than 16-bits and would be subject
697 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800699inline static QCBORError
700DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700702 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
705 if (uNumber <= INT64_MAX) {
706 pDecodedItem->val.int64 = (int64_t)uNumber;
707 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800708
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709 } else {
710 pDecodedItem->val.uint64 = uNumber;
711 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800712
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 }
714 } else {
715 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800716 // CBOR's representation of negative numbers lines up with the
717 // two-compliment representation. A negative integer has one
718 // more in range than a positive integer. INT64_MIN is
719 // equal to (-INT64_MAX) - 1.
720 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723 } else {
724 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000725 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726 nReturn = QCBOR_ERR_INT_OVERFLOW;
727 }
728 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800729
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 return nReturn;
731}
732
733// Make sure #define value line up as DecodeSimple counts on this.
734#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
735#error QCBOR_TYPE_FALSE macro value wrong
736#endif
737
738#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
739#error QCBOR_TYPE_TRUE macro value wrong
740#endif
741
742#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
743#error QCBOR_TYPE_NULL macro value wrong
744#endif
745
746#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
747#error QCBOR_TYPE_UNDEF macro value wrong
748#endif
749
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700750#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
751#error QCBOR_TYPE_BREAK macro value wrong
752#endif
753
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700754#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
755#error QCBOR_TYPE_DOUBLE macro value wrong
756#endif
757
758#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
759#error QCBOR_TYPE_FLOAT macro value wrong
760#endif
761
762/*
763 Decode true, false, floats, break...
764 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800765inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700768 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundbladeee851742020-01-08 08:37:05 -0800770 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800771 // above make sure uAdditionalInfo values line up with uDataType values.
772 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
773 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800774
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800775 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800776 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
777 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800778
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700779 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700780 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
781 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700782 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700783 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700784 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
785 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700786 break;
787 case DOUBLE_PREC_FLOAT:
788 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700789 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700790 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792 case CBOR_SIMPLEV_FALSE: // 20
793 case CBOR_SIMPLEV_TRUE: // 21
794 case CBOR_SIMPLEV_NULL: // 22
795 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700796 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799 case CBOR_SIMPLEV_ONEBYTE: // 24
800 if(uNumber <= CBOR_SIMPLE_BREAK) {
801 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700802 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 goto Done;
804 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800805 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700808 default: // 0-19
809 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800810 /*
811 DecodeTypeAndNumber will make uNumber equal to
812 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
813 safe because the 2, 4 and 8 byte lengths of uNumber are in
814 the double/float cases above
815 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 pDecodedItem->val.uSimple = (uint8_t)uNumber;
817 break;
818 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800819
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820Done:
821 return nReturn;
822}
823
824
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530826 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800828inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
829 int nMajorType,
830 uint64_t uStrLen,
831 UsefulInputBuf *pUInBuf,
832 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700834 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800836 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
837 // This check makes the casts to size_t below safe.
838
839 // 4 bytes less than the largest sizeof() so this can be tested by
840 // putting a SIZE_MAX length in the CBOR test input (no one will
841 // care the limit on strings is 4 bytes shorter).
842 if(uStrLen > SIZE_MAX-4) {
843 nReturn = QCBOR_ERR_STRING_TOO_LONG;
844 goto Done;
845 }
846
847 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530848 if(UsefulBuf_IsNULLC(Bytes)) {
849 // Failed to get the bytes for this string item
850 nReturn = QCBOR_ERR_HIT_END;
851 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530853
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800854 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530855 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800856 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530857 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700858 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530859 goto Done;
860 }
861 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800862 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530863 } else {
864 // Normal case with no string allocator
865 pDecodedItem->val.string = Bytes;
866 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800867 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 // Cast because ternary operator causes promotion to integer
869 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
870 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873 return nReturn;
874}
875
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700876
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800877
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700878
879
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880
881
Laurence Lundbladeee851742020-01-08 08:37:05 -0800882// Make sure the constants align as this is assumed by
883// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
885#error QCBOR_TYPE_ARRAY value not lined up with major type
886#endif
887#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
888#error QCBOR_TYPE_MAP value not lined up with major type
889#endif
890
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700891/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800892 This gets a single data item and decodes it including preceding
893 optional tagging. This does not deal with arrays and maps and nesting
894 except to decode the data item introducing them. Arrays and maps are
895 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundbladeee851742020-01-08 08:37:05 -0800897 Errors detected here include: an array that is too long to decode,
898 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700899 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800900static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
901 QCBORItem *pDecodedItem,
902 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700904 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladeee851742020-01-08 08:37:05 -0800906 /*
907 Get the major type and the number. Number could be length of more
908 bytes or the value depending on the major type nAdditionalInfo is
909 an encoding of the length of the uNumber and is needed to decode
910 floats and doubles
911 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800912 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700913 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800914 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700916 memset(pDecodedItem, 0, sizeof(QCBORItem));
917
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800918 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800919
Laurence Lundbladeee851742020-01-08 08:37:05 -0800920 // Error out here if we got into trouble on the type and number. The
921 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700922 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700924 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundbladeee851742020-01-08 08:37:05 -0800926 // At this point the major type and the value are valid. We've got
927 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800928 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700929 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
930 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700932 nReturn = QCBOR_ERR_BAD_INT;
933 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800934 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700935 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
939 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800940 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
941 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
942 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
943 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530944 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700945 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800946 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700947 }
948 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
951 case CBOR_MAJOR_TYPE_MAP: // Major type 5
952 // Record the number of items in the array or map
953 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
954 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
955 goto Done;
956 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800957 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700958 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700959 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800960 // type conversion OK because of check above
961 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800963 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
965 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700966 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800967
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800969 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700970 nReturn = QCBOR_ERR_BAD_INT;
971 } else {
972 pDecodedItem->val.uTagV = uNumber;
973 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
974 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundbladeee851742020-01-08 08:37:05 -0800977 case CBOR_MAJOR_TYPE_SIMPLE:
978 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800979 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700980 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundbladeee851742020-01-08 08:37:05 -0800982 default:
983 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 nReturn = QCBOR_ERR_UNSUPPORTED;
985 break;
986 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800987
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988Done:
989 return nReturn;
990}
991
992
993
994/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800995 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800996 individual chunk items together into one QCBORItem using the string
997 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530999 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001static inline QCBORError
1002GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001004 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001005
1006 // Get pointer to string allocator. First use is to pass it to
1007 // GetNext_Item() when option is set to allocate for *every* string.
1008 // Second use here is to allocate space to coallese indefinite
1009 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001010 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1011 &(me->StringAllocator) :
1012 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001014 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001015 nReturn = GetNext_Item(&(me->InBuf),
1016 pDecodedItem,
1017 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 if(nReturn) {
1019 goto Done;
1020 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301023 // code in this function from here down can be eliminated. Run tests, except
1024 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001026 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001027 const uint8_t uStringType = pDecodedItem->uDataType;
1028 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 goto Done; // no need to do any work here on non-string types
1030 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001031
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001032 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301033 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001034 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001036
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301037 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001038 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001039 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1040 goto Done;
1041 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001042
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001043 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001044 UsefulBufC FullString = NULLUsefulBufC;
1045
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001047 // Get item for next chunk
1048 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001049 // NULL string allocator passed here. Do not need to allocate
1050 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001051 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001053 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301056 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001057 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001058 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301060 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 break;
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001064 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301065 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001066 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001067 if(StringChunkItem.uDataType != uStringType ||
1068 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001069 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 break;
1071 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301073 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001074 // The first time throurgh FullString.ptr is NULL and this is
1075 // equivalent to StringAllocator_Allocate()
1076 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1077 UNCONST_POINTER(FullString.ptr),
1078 FullString.len + StringChunkItem.val.string.len);
1079
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301081 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001082 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 break;
1084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001086 // Copy new string chunk at the end of string so far.
1087 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001088 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001089
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001090 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1091 // Getting the item failed, clean up the allocated memory
1092 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001094
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001095Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 return nReturn;
1097}
1098
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001099
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001100static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1101 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001102 return uTagVal;
1103 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001104 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001105 return me->auMappedTags[x];
1106 }
1107}
1108
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001109/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001110 Gets all optional tag data items preceding a data item that is not an
1111 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001112 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001113static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001114GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001115{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001116 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001117
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001118 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1119 CBOR_TAG_INVALID16,
1120 CBOR_TAG_INVALID16,
1121 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001122
Laurence Lundblade59289e52019-12-30 13:44:37 -08001123 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001124 for(;;) {
1125 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001126 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001127 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001128 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001129
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001130 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1131 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001132 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001133 break;
1134 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001135
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001136 // Is there room for the tag in the tags list?
1137 size_t uTagIndex;
1138 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001139 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001140 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001141 }
1142 }
1143 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001144 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001145 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001146
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001147 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001148 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001149 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001150 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001152 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001153 break;
1154 }
1155 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001156 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001157 break;
1158 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001159 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1161 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001162 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1163 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001164 }
1165
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001166 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001167 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001168 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001169
1170 } else {
1171 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001172 }
1173 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001175Done:
1176 return nReturn;
1177}
1178
1179
1180/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001181 This layer takes care of map entries. It combines the label and data
1182 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001183 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001184static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001185GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001186{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001187 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001189 if(nReturn)
1190 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001192 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001193 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001194 goto Done;
1195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001196
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001197 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1198 // In a map and caller wants maps decoded, not treated as arrays
1199
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001200 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001201 // If in a map and the right decoding mode, get the label
1202
Laurence Lundbladeee851742020-01-08 08:37:05 -08001203 // Save label in pDecodedItem and get the next which will
1204 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001205 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001206 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001207 if(nReturn)
1208 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001209
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301210 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001211
1212 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1213 // strings are always good labels
1214 pDecodedItem->label.string = LabelItem.val.string;
1215 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1216 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001217 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001218 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1219 goto Done;
1220 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1221 pDecodedItem->label.int64 = LabelItem.val.int64;
1222 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1223 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1224 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1225 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1226 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1227 pDecodedItem->label.string = LabelItem.val.string;
1228 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1229 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1230 } else {
1231 // label is not an int or a string. It is an arrray
1232 // or a float or such and this implementation doesn't handle that.
1233 // Also, tags on labels are ignored.
1234 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1235 goto Done;
1236 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001237 }
1238 } else {
1239 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001240 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1241 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1242 goto Done;
1243 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001244 // Decoding a map as an array
1245 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001246 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1247 // Cast is needed because of integer promotion
1248 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001249 }
1250 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001252Done:
1253 return nReturn;
1254}
1255
1256
Laurence Lundblade02625d42020-06-25 14:41:41 -07001257/*
1258 See if next item is a CBOR break. If it is, it is consumed,
1259 if not it is not consumed.
1260*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001261static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001262NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1263{
1264 *pbNextIsBreak = false;
1265 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001266 QCBORItem Peek;
1267 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1268 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1269 if(uReturn != QCBOR_SUCCESS) {
1270 return uReturn;
1271 }
1272 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001273 // It is not a break, rewind so it can be processed normally.
1274 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001275 } else {
1276 *pbNextIsBreak = true;
1277 }
1278 }
1279
1280 return QCBOR_SUCCESS;
1281}
1282
1283
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001284/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001285 An item was just consumed, now figure out if it was the
1286 end of an array or map that can be closed out. That
1287 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001288*/
Laurence Lundblade02625d42020-06-25 14:41:41 -07001289static QCBORError NestLevelAscender(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001290{
1291 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001292
Laurence Lundblade642282a2020-06-23 12:00:33 -07001293 /* This loops ascending nesting levels as long as there is ascending to do */
1294 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1295
1296 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001297 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001298 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1299 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001300 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001301 break;
1302 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001303 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001304
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001305 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001306 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001307 bool bIsBreak = false;
1308 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1309 if(uReturn != QCBOR_SUCCESS) {
1310 goto Done;
1311 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001312
1313 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001314 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001315 break;
1316 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001317
1318 if(DecodeNesting_IsBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001319 /*
1320 Break occurred inside a bstr-wrapped CBOR or
1321 in the top level sequence. This is always an
1322 error because neither are an indefinte length
1323 map/array.
1324 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001325 uReturn = QCBOR_ERR_BAD_BREAK;
1326 goto Done;
1327 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001328 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001329 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001330
Laurence Lundblade02625d42020-06-25 14:41:41 -07001331 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001332
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001333 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001334 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001335 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001336 DecodeNesting_ZeroDefiniteLengthCount(&(pMe->nesting));
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001337 break;
1338 }
1339
1340 /* Finally, actually ascend one level. */
1341 DecodeNesting_Ascend(&(pMe->nesting));
1342 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001343
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001344 uReturn = QCBOR_SUCCESS;
1345
1346Done:
1347 return uReturn;
1348}
1349
1350
1351/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001352 This the travesal going descending into and asecnding out of maps,
1353 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1354 indefinte length maps and arrays by looking at the item count or
1355 finding CBOR breaks. It detects the ends of the top-level sequence
1356 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001357 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001358static QCBORError
1359QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001360{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001361 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001362 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001363
Laurence Lundblade642282a2020-06-23 12:00:33 -07001364 /*
1365 If out of bytes to consume, it is either the end of the top-level
1366 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001367
Laurence Lundblade642282a2020-06-23 12:00:33 -07001368 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1369 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1370 CBOR is exited, the length is set back to the top-level's length
1371 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001372
Laurence Lundblade642282a2020-06-23 12:00:33 -07001373 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1374 when at the top level to allow other code below to process various
1375 errors when out of bytes to decode and not at the top level. Note
1376 that QCBORDecode_Finish() still needs to be called to be sure all
1377 nesting levels were closed out.
1378 */
1379 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1380 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001381 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001382 goto Done;
1383 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001384
Laurence Lundblade642282a2020-06-23 12:00:33 -07001385 /*
1386 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001387 array. The check for the end of an indefinite length array is
1388 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001389 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001391 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001392 goto Done;
1393 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001394
Laurence Lundblade642282a2020-06-23 12:00:33 -07001395 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 uReturn = GetNext_MapEntry(me, pDecodedItem);
1397 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001398 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001399 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301400
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401 /*
1402 Breaks ending arrays/maps are always processed at the end of this
1403 function. They should never show up here.
1404 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301405 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001406 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301407 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001409
Laurence Lundblade642282a2020-06-23 12:00:33 -07001410 /*
1411 Record the nesting level for this data item before processing any
1412 of decrementing and descending.
1413 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001414 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001415
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416
1417 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001419 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001420 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421
Laurence Lundblade02625d42020-06-25 14:41:41 -07001422 Empty maps and arrays descended into, but then ascended out
1423 of in the next chunk of code.
1424
1425 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426 encloses them so a decrement needs to be done for them too, but
1427 that is done only when all the items in them have been
1428 processed, not when they are opened with the exception of an
1429 empty map or array.
1430 */
1431 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1432 pDecodedItem->uDataType,
1433 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001434 if(uReturn != QCBOR_SUCCESS) {
1435 goto Done;
1436 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001437 }
1438
Laurence Lundblade02625d42020-06-25 14:41:41 -07001439 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1440 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1441 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001442 /*
1443 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001444 - A non-aggregate like an integer or string
1445 - An empty definite length map or array
1446 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447
1448 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001449 definite length map/array and break detection for an indefinite
1450 length map/array. If the end of the map/array was reached, then
1451 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001452 */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001453 uReturn = NestLevelAscender(me);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001454 if(uReturn) {
1455 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001456 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301457 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001458
Laurence Lundblade02625d42020-06-25 14:41:41 -07001459 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001461 Tell the caller what level is next. This tells them what
1462 maps/arrays were closed out and makes it possible for them to
1463 reconstruct the tree with just the information returned in
1464 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465 */
1466 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001467 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001468 pDecodedItem->uNextNestLevel = 0;
1469 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001470 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001471 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001473Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001474 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001475 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001476 memset(pDecodedItem, 0, sizeof(QCBORItem));
1477 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001478 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001479}
1480
1481
Laurence Lundblade59289e52019-12-30 13:44:37 -08001482/*
1483 Mostly just assign the right data type for the date string.
1484 */
1485inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1486{
1487 // Stack Use: UsefulBuf 1 16
1488 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1489 return QCBOR_ERR_BAD_OPT_TAG;
1490 }
1491
1492 const UsefulBufC Temp = pDecodedItem->val.string;
1493 pDecodedItem->val.dateString = Temp;
1494 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1495 return QCBOR_SUCCESS;
1496}
1497
1498
1499/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001500 The epoch formatted date. Turns lots of different forms of encoding
1501 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001502 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001503static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001504{
1505 // Stack usage: 1
1506 QCBORError nReturn = QCBOR_SUCCESS;
1507
1508 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1509
1510 switch (pDecodedItem->uDataType) {
1511
1512 case QCBOR_TYPE_INT64:
1513 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1514 break;
1515
1516 case QCBOR_TYPE_UINT64:
1517 if(pDecodedItem->val.uint64 > INT64_MAX) {
1518 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1519 goto Done;
1520 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001521 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001522 break;
1523
1524 case QCBOR_TYPE_DOUBLE:
1525 {
1526 // This comparison needs to be done as a float before
1527 // conversion to an int64_t to be able to detect doubles
1528 // that are too large to fit into an int64_t. A double
1529 // has 52 bits of preceision. An int64_t has 63. Casting
1530 // INT64_MAX to a double actually causes a round up which
1531 // is bad and wrong for the comparison because it will
1532 // allow conversion of doubles that can't fit into a
1533 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1534 // the cutoff point as if that rounds up in conversion to
1535 // double it will still be less than INT64_MAX. 0x7ff is
1536 // picked because it has 11 bits set.
1537 //
1538 // INT64_MAX seconds is on the order of 10 billion years,
1539 // and the earth is less than 5 billion years old, so for
1540 // most uses this conversion error won't occur even though
1541 // doubles can go much larger.
1542 //
1543 // Without the 0x7ff there is a ~30 minute range of time
1544 // values 10 billion years in the past and in the future
1545 // where this this code would go wrong.
1546 const double d = pDecodedItem->val.dfnum;
1547 if(d > (double)(INT64_MAX - 0x7ff)) {
1548 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1549 goto Done;
1550 }
1551 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1552 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1553 }
1554 break;
1555
1556 default:
1557 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1558 goto Done;
1559 }
1560 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1561
1562Done:
1563 return nReturn;
1564}
1565
1566
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001567/*
1568 Mostly just assign the right data type for the bignum.
1569 */
1570inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1571{
1572 // Stack Use: UsefulBuf 1 -- 16
1573 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1574 return QCBOR_ERR_BAD_OPT_TAG;
1575 }
1576 const UsefulBufC Temp = pDecodedItem->val.string;
1577 pDecodedItem->val.bigNum = Temp;
1578 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1579 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1580 : QCBOR_TYPE_NEGBIGNUM);
1581 return QCBOR_SUCCESS;
1582}
1583
1584
Laurence Lundblade59289e52019-12-30 13:44:37 -08001585#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1586/*
1587 Decode decimal fractions and big floats.
1588
1589 When called pDecodedItem must be the array that is tagged as a big
1590 float or decimal fraction, the array that has the two members, the
1591 exponent and mantissa.
1592
1593 This will fetch and decode the exponent and mantissa and put the
1594 result back into pDecodedItem.
1595 */
1596inline static QCBORError
1597QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1598{
1599 QCBORError nReturn;
1600
1601 // --- Make sure it is an array; track nesting level of members ---
1602 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1603 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1604 goto Done;
1605 }
1606
1607 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001608 // definite length arrays, but not for indefnite. Instead remember
1609 // the nesting level the two integers must be at, which is one
1610 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001611 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1612
1613 // --- Is it a decimal fraction or a bigfloat? ---
1614 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1615 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1616
1617 // --- Get the exponent ---
1618 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001619 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001620 if(nReturn != QCBOR_SUCCESS) {
1621 goto Done;
1622 }
1623 if(exponentItem.uNestingLevel != nNestLevel) {
1624 // Array is empty or a map/array encountered when expecting an int
1625 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1626 goto Done;
1627 }
1628 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1629 // Data arriving as an unsigned int < INT64_MAX has been converted
1630 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1631 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1632 // will be too large for this to handle and thus an error that will
1633 // get handled in the next else.
1634 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1635 } else {
1636 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1637 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1638 goto Done;
1639 }
1640
1641 // --- Get the mantissa ---
1642 QCBORItem mantissaItem;
1643 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1644 if(nReturn != QCBOR_SUCCESS) {
1645 goto Done;
1646 }
1647 if(mantissaItem.uNestingLevel != nNestLevel) {
1648 // Mantissa missing or map/array encountered when expecting number
1649 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1650 goto Done;
1651 }
1652 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1653 // Data arriving as an unsigned int < INT64_MAX has been converted
1654 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1655 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1656 // will be too large for this to handle and thus an error that
1657 // will get handled in an else below.
1658 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1659 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1660 // Got a good big num mantissa
1661 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1662 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001663 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1664 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1665 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001666 } else {
1667 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1668 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1669 goto Done;
1670 }
1671
1672 // --- Check that array only has the two numbers ---
1673 if(mantissaItem.uNextNestLevel == nNestLevel) {
1674 // Extra items in the decimal fraction / big num
1675 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1676 goto Done;
1677 }
1678
1679Done:
1680
1681 return nReturn;
1682}
1683#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1684
1685
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001686
1687/*
1688 */
1689inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1690{
1691 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1692 return QCBOR_ERR_BAD_OPT_TAG;
1693 }
1694 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1695 return QCBOR_SUCCESS;
1696}
1697
1698
1699inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1700{
1701 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1702 return QCBOR_ERR_BAD_OPT_TAG;
1703 }
1704 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1705 return QCBOR_SUCCESS;
1706}
1707
1708
1709inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1710{
1711 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1712 return QCBOR_ERR_BAD_OPT_TAG;
1713 }
1714 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1715 return QCBOR_SUCCESS;
1716}
1717
1718
1719inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1720{
1721 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1722 return QCBOR_ERR_BAD_OPT_TAG;
1723 }
1724 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1725 return QCBOR_SUCCESS;
1726}
1727
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001728inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1729{
1730 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1731 return QCBOR_ERR_BAD_OPT_TAG;
1732 }
1733 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1734 return QCBOR_SUCCESS;
1735}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001736
1737inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1738{
1739 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1740 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1741 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1742 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1743 } else {
1744 return QCBOR_ERR_BAD_OPT_TAG;
1745 }
1746 return QCBOR_SUCCESS;
1747}
1748
1749
1750/*
1751 */
1752inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1753{
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1755 return QCBOR_ERR_BAD_OPT_TAG;
1756 }
1757 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1758 return QCBOR_SUCCESS;
1759}
1760
1761
Laurence Lundblade59289e52019-12-30 13:44:37 -08001762/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001763 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001765QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001766QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767{
1768 QCBORError nReturn;
1769
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001770 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001771 if(nReturn != QCBOR_SUCCESS) {
1772 goto Done;
1773 }
1774
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001775 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1776 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001777
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001778 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779 nReturn = DecodeDateString(pDecodedItem);
1780 break;
1781
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001782 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001783 nReturn = DecodeDateEpoch(pDecodedItem);
1784 break;
1785
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001786 case CBOR_TAG_POS_BIGNUM:
1787 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788 nReturn = DecodeBigNum(pDecodedItem);
1789 break;
1790
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001791 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1792 case CBOR_TAG_DECIMAL_FRACTION:
1793 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001794 // For aggregate tagged types, what goes into pTags is only collected
1795 // from the surrounding data item, not the contents, so pTags is not
1796 // passed on here.
1797
1798 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1799 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001800 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001801
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001802 case CBOR_TAG_CBOR:
1803 nReturn = DecodeWrappedCBOR(pDecodedItem);
1804 break;
1805
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001806 case CBOR_TAG_URI:
1807 nReturn = DecodeURI(pDecodedItem);
1808 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001809
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001810 case CBOR_TAG_B64URL:
1811 nReturn = DecodeB64URL(pDecodedItem);
1812 break;
1813
1814 case CBOR_TAG_B64:
1815 nReturn = DecodeB64(pDecodedItem);
1816 break;
1817
1818 case CBOR_TAG_MIME:
1819 case CBOR_TAG_BINARY_MIME:
1820 nReturn = DecodeMIME(pDecodedItem);
1821 break;
1822
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001823 case CBOR_TAG_REGEX:
1824 nReturn = DecodeRegex(pDecodedItem);
1825 break;
1826
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001827 case CBOR_TAG_BIN_UUID:
1828 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001829 break;
1830
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001831 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001832 // The end of the tag list or no tags
1833 // Successful exit from the loop.
1834 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001835
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001836 default:
1837 // A tag that is not understood
1838 // A successful exit from the loop
1839 goto Done;
1840
1841 }
1842 if(nReturn != QCBOR_SUCCESS) {
1843 goto Done;
1844 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001845 }
1846
1847Done:
1848 if(nReturn != QCBOR_SUCCESS) {
1849 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1850 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1851 }
1852 return nReturn;
1853}
1854
1855
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001856QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1857{
1858 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1859
1860 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1861
1862 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1863
1864 return uErr;
1865}
1866
1867
Laurence Lundblade59289e52019-12-30 13:44:37 -08001868/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001869 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001870 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001871QCBORError
1872QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1873 QCBORItem *pDecodedItem,
1874 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001875{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001876 QCBORError nReturn;
1877
1878 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1879 if(nReturn != QCBOR_SUCCESS) {
1880 return nReturn;
1881 }
1882
1883 if(pTags != NULL) {
1884 pTags->uNumUsed = 0;
1885 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001886 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001887 break;
1888 }
1889 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1890 return QCBOR_ERR_TOO_MANY_TAGS;
1891 }
1892 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1893 pTags->uNumUsed++;
1894 }
1895 }
1896
1897 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001898}
1899
1900
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001901/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301902 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301903 next one down. If a layer has no work to do for a particular item
1904 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001905
Laurence Lundblade59289e52019-12-30 13:44:37 -08001906 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1907 tagged data items, turning them into the local C representation.
1908 For the most simple it is just associating a QCBOR_TYPE with the data. For
1909 the complex ones that an aggregate of data items, there is some further
1910 decoding and a little bit of recursion.
1911
1912 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301913 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301914 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001915 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001916
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301917 - GetNext_MapEntry -- This handles the combining of two
1918 items, the label and the data, that make up a map entry.
1919 It only does work on maps. It combines the label and data
1920 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001921
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1923 tags into bit flags associated with the data item. No actual decoding
1924 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001925
Laurence Lundblade59289e52019-12-30 13:44:37 -08001926 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301927 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301928 string allocater to create contiguous space for the item. It
1929 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001930
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1932 atomic data item has a "major type", an integer "argument" and optionally
1933 some content. For text and byte strings, the content is the bytes
1934 that make up the string. These are the smallest data items that are
1935 considered to be well-formed. The content may also be other data items in
1936 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001937
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001938 Roughly this takes 300 bytes of stack for vars. Need to
1939 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001940
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301941 */
1942
1943
1944/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001945 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001946 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001947int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001948 const QCBORItem *pItem,
1949 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001950{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001951 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001952 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001953 break;
1954 }
1955 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1956 return 1;
1957 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001958 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001959
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001960 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001961}
1962
1963
1964/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001965 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001966 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001967QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001968{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001969 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001970
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001971 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001972 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001973 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1974 goto Done;
1975 }
1976
1977 // Error out if not all the bytes are consumed
1978 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1979 nReturn = QCBOR_ERR_EXTRA_BYTES;
1980 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001981
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001982Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301983 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001984 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001985 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001986
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001987 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001988}
1989
1990
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001991/*
1992Public function, see header qcbor/qcbor_decode.h file
1993*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001994uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1995 const QCBORItem *pItem,
1996 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001997{
1998 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
1999 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002000 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002001 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002002 }
2003}
2004
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002005
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002006/*
2007
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002008Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002009
Laurence Lundbladeee851742020-01-08 08:37:05 -08002010 - Hit end of input before it was expected while decoding type and
2011 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002012
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002013 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002014
Laurence Lundbladeee851742020-01-08 08:37:05 -08002015 - Hit end of input while decoding a text or byte string
2016 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002017
Laurence Lundbladeee851742020-01-08 08:37:05 -08002018 - Encountered conflicting tags -- e.g., an item is tagged both a date
2019 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundbladeee851742020-01-08 08:37:05 -08002021 - Encontered an array or mapp that has too many items
2022 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023
Laurence Lundbladeee851742020-01-08 08:37:05 -08002024 - Encountered array/map nesting that is too deep
2025 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002026
Laurence Lundbladeee851742020-01-08 08:37:05 -08002027 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2028 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002029
Laurence Lundbladeee851742020-01-08 08:37:05 -08002030 - The type of a map label is not a string or int
2031 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002032
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002033 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002034
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002035 */
2036
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002037
2038
Laurence Lundbladef6531662018-12-04 10:42:22 +09002039
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002040/* ===========================================================================
2041 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002042
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002043 This implements a simple sting allocator for indefinite length
2044 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2045 implements the function type QCBORStringAllocate and allows easy
2046 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002047
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002048 This particular allocator is built-in for convenience. The caller
2049 can implement their own. All of this following code will get
2050 dead-stripped if QCBORDecode_SetMemPool() is not called.
2051
2052 This is a very primitive memory allocator. It does not track
2053 individual allocations, only a high-water mark. A free or
2054 reallocation must be of the last chunk allocated.
2055
2056 The size of the pool and offset to free memory are packed into the
2057 first 8 bytes of the memory pool so we don't have to keep them in
2058 the decode context. Since the address of the pool may not be
2059 aligned, they have to be packed and unpacked as if they were
2060 serialized data of the wire or such.
2061
2062 The sizes packed in are uint32_t to be the same on all CPU types
2063 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002064 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002065
2066
Laurence Lundbladeee851742020-01-08 08:37:05 -08002067static inline int
2068MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002069{
2070 // Use of UsefulInputBuf is overkill, but it is convenient.
2071 UsefulInputBuf UIB;
2072
Laurence Lundbladeee851742020-01-08 08:37:05 -08002073 // Just assume the size here. It was checked during SetUp so
2074 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002075 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2076 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2077 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2078 return UsefulInputBuf_GetError(&UIB);
2079}
2080
2081
Laurence Lundbladeee851742020-01-08 08:37:05 -08002082static inline int
2083MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002084{
2085 // Use of UsefulOutBuf is overkill, but convenient. The
2086 // length check performed here is useful.
2087 UsefulOutBuf UOB;
2088
2089 UsefulOutBuf_Init(&UOB, Pool);
2090 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2091 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2092 return UsefulOutBuf_GetError(&UOB);
2093}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002094
2095
2096/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002097 Internal function for an allocation, reallocation free and destuct.
2098
2099 Having only one function rather than one each per mode saves space in
2100 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002101
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002102 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2103 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002104static UsefulBuf
2105MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002106{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002107 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002108
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002109 uint32_t uPoolSize;
2110 uint32_t uFreeOffset;
2111
2112 if(uNewSize > UINT32_MAX) {
2113 // This allocator is only good up to 4GB. This check should
2114 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2115 goto Done;
2116 }
2117 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2118
2119 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2120 goto Done;
2121 }
2122
2123 if(uNewSize) {
2124 if(pMem) {
2125 // REALLOCATION MODE
2126 // Calculate pointer to the end of the memory pool. It is
2127 // assumed that pPool + uPoolSize won't wrap around by
2128 // assuming the caller won't pass a pool buffer in that is
2129 // not in legitimate memory space.
2130 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2131
2132 // Check that the pointer for reallocation is in the range of the
2133 // pool. This also makes sure that pointer math further down
2134 // doesn't wrap under or over.
2135 if(pMem >= pPool && pMem < pPoolEnd) {
2136 // Offset to start of chunk for reallocation. This won't
2137 // wrap under because of check that pMem >= pPool. Cast
2138 // is safe because the pool is always less than UINT32_MAX
2139 // because of check in QCBORDecode_SetMemPool().
2140 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2141
2142 // Check to see if the allocation will fit. uPoolSize -
2143 // uMemOffset will not wrap under because of check that
2144 // pMem is in the range of the uPoolSize by check above.
2145 if(uNewSize <= uPoolSize - uMemOffset) {
2146 ReturnValue.ptr = pMem;
2147 ReturnValue.len = uNewSize;
2148
2149 // Addition won't wrap around over because uNewSize was
2150 // checked to be sure it is less than the pool size.
2151 uFreeOffset = uMemOffset + uNewSize32;
2152 }
2153 }
2154 } else {
2155 // ALLOCATION MODE
2156 // uPoolSize - uFreeOffset will not underflow because this
2157 // pool implementation makes sure uFreeOffset is always
2158 // smaller than uPoolSize through this check here and
2159 // reallocation case.
2160 if(uNewSize <= uPoolSize - uFreeOffset) {
2161 ReturnValue.len = uNewSize;
2162 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002163 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002164 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002165 }
2166 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002167 if(pMem) {
2168 // FREE MODE
2169 // Cast is safe because of limit on pool size in
2170 // QCBORDecode_SetMemPool()
2171 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2172 } else {
2173 // DESTRUCT MODE
2174 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002175 }
2176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002177
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002178 UsefulBuf Pool = {pPool, uPoolSize};
2179 MemPool_Pack(Pool, uFreeOffset);
2180
2181Done:
2182 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002183}
2184
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002185
Laurence Lundbladef6531662018-12-04 10:42:22 +09002186/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002187 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002188 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002189QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2190 UsefulBuf Pool,
2191 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002192{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002193 // The pool size and free mem offset are packed into the beginning
2194 // of the pool memory. This compile time check make sure the
2195 // constant in the header is correct. This check should optimize
2196 // down to nothing.
2197 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002198 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002200
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002201 // The pool size and free offset packed in to the beginning of pool
2202 // memory are only 32-bits. This check will optimize out on 32-bit
2203 // machines.
2204 if(Pool.len > UINT32_MAX) {
2205 return QCBOR_ERR_BUFFER_TOO_LARGE;
2206 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002207
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002208 // This checks that the pool buffer given is big enough.
2209 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2210 return QCBOR_ERR_BUFFER_TOO_SMALL;
2211 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002212
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002213 pMe->StringAllocator.pfAllocator = MemPool_Function;
2214 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2215 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002216
Laurence Lundblade30816f22018-11-10 13:40:22 +07002217 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002218}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002219
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002220
2221
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002222
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002223
2224
2225/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002226 Consume an entire map or array (and do next to
2227 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002228 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002229static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002230ConsumeItem(QCBORDecodeContext *pMe,
2231 const QCBORItem *pItemToConsume,
2232 uint_fast8_t *puNextNestLevel)
2233{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002234 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002235 QCBORItem Item;
2236
Laurence Lundblade02625d42020-06-25 14:41:41 -07002237 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002238
Laurence Lundblade02625d42020-06-25 14:41:41 -07002239 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002240 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002241
Laurence Lundblade1341c592020-04-11 14:19:05 -07002242 /* This works for definite and indefinite length
2243 * maps and arrays by using the nesting level
2244 */
2245 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002246 uReturn = QCBORDecode_GetNext(pMe, &Item);
2247 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002248 goto Done;
2249 }
2250 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002251
Laurence Lundblade1341c592020-04-11 14:19:05 -07002252 if(puNextNestLevel != NULL) {
2253 *puNextNestLevel = Item.uNextNestLevel;
2254 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002255 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002256
Laurence Lundblade1341c592020-04-11 14:19:05 -07002257 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002258 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002259 if(puNextNestLevel != NULL) {
2260 /* Just pass the nesting level through */
2261 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2262 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002263 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002264 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002265
2266Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002268}
2269
2270
Laurence Lundblade1341c592020-04-11 14:19:05 -07002271/* Return true if the labels in Item1 and Item2 are the same.
2272 Works only for integer and string labels. Returns false
2273 for any other type. */
2274static inline bool
2275MatchLabel(QCBORItem Item1, QCBORItem Item2)
2276{
2277 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2278 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2279 return true;
2280 }
2281 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002282 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283 return true;
2284 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002285 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002286 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2287 return true;
2288 }
2289 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2290 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2291 return true;
2292 }
2293 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002294
Laurence Lundblade1341c592020-04-11 14:19:05 -07002295 /* Other label types are never matched */
2296 return false;
2297}
2298
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002299
2300/*
2301 Returns true if Item1 and Item2 are the same type
2302 or if either are of QCBOR_TYPE_ANY.
2303 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002304static inline bool
2305MatchType(QCBORItem Item1, QCBORItem Item2)
2306{
2307 if(Item1.uDataType == Item2.uDataType) {
2308 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002309 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002310 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002311 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002312 return true;
2313 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002314 return false;
2315}
2316
2317
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002318/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002319 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002320
2321 @param[in] pMe The decode context to search.
2322 @param[in,out] pItemArray The items to search for and the items found.
2323 @param[in] pCBContext Context for the not-found item call back
2324 @param[in] pfCallback Function to call on items not matched in pItemArray
2325
2326 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2327
2328 @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.
2329
2330 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2331
2332 @retval Also errors returned by QCBORDecode_GetNext().
2333
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002334 On input pItemArray contains a list of labels and data types
2335 of items to be found.
2336
2337 On output the fully retrieved items are filled in with
2338 values and such. The label was matched, so it never changes.
2339
2340 If an item was not found, its data type is set to none.
2341
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002342 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002343static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002344MapSearch(QCBORDecodeContext *pMe,
2345 QCBORItem *pItemArray,
2346 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002347 void *pCBContext,
2348 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002349{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002350 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002351
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002352 QCBORDecodeNesting SaveNesting;
2353 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002354
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002355 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002356 UsefulInputBuf_Seek(&(pMe->InBuf),
2357 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002358
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002359 /*
2360 Loop over all the items in the map. They could be
2361 deeply nested and this should handle both definite
2362 and indefinite length maps and arrays, so this
2363 adds some complexity.
2364 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002365 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002366
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002367 uint_fast8_t uNextNestLevel;
2368
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002369 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002370
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002371 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002372 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002373 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002374 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002376 /* Get the item */
2377 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002378 uReturn = QCBORDecode_GetNext(pMe, &Item);
2379 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002380 /* Got non-well-formed CBOR */
2381 goto Done;
2382 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002383
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002384 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002385 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002386 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002387 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002388 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002389 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2391 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002392 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002393 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002394 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002395 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002396 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002397 goto Done;
2398 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002399
2400 /* Successful match. Return the item. */
2401 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002402 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002403 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002404 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002405 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002406 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002407 /*
2408 Call the callback on unmatched labels.
2409 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002410 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002411 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002412 */
2413 if(pfCallback) {
2414 uReturn = (*pfCallback)(pCBContext, &Item);
2415 if(uReturn != QCBOR_SUCCESS) {
2416 goto Done;
2417 }
2418 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002419 }
2420 }
2421
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002422 /*
2423 Consume the item whether matched or not. This
2424 does the work of traversing maps and array and
2425 everything in them. In this loop only the
2426 items at the current nesting level are examined
2427 to match the labels.
2428 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002429 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2430 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002431 goto Done;
2432 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002433
2434 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002435
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002436 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002437
2438 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002439 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2440 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002441
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002442 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002443 int i;
2444 QCBORItem *pIterator;
2445 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002446 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002447 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002448 }
2449 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002450
2451Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002452 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002453
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002454 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002455}
2456
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002457
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002458/*
2459Public function, see header qcbor/qcbor_decode.h file
2460*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002461void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2462 int64_t nLabel,
2463 uint8_t uQcborType,
2464 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002465{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002466 if(pMe->uLastError != QCBOR_SUCCESS) {
2467 return;
2468 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002469
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002470 QCBORItem OneItemSeach[2];
2471 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2472 OneItemSeach[0].label.int64 = nLabel;
2473 OneItemSeach[0].uDataType = uQcborType;
2474 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002475
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002476 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002477 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002478 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479 }
2480
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002481 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2482 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483 }
2484
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002485 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002486}
2487
2488
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002489/*
2490Public function, see header qcbor/qcbor_decode.h file
2491*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002492void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2493 const char *szLabel,
2494 uint8_t uQcborType,
2495 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002496{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002497 if(pMe->uLastError != QCBOR_SUCCESS) {
2498 return;
2499 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002500
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002501 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002502 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2503 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2504 OneItemSeach[0].uDataType = uQcborType;
2505 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002506
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002507 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002509 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002510 }
2511
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002512 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002513 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002514 }
2515
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002516 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002517}
2518
2519
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002520/**
2521 @param[in] TagSpec Specification for matching tags.
2522 @param[in] uDataType A QCBOR data type
2523
2524 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2525 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2526
2527 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2528 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002529static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002530{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002531 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2532 /* Must match the tag */
2533 if(uDataType == TagSpec.uTaggedType) {
2534 return QCBOR_SUCCESS;
2535 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002536 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002537 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2538 /* Must check all the possible types for the tag content */
2539 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002540 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2541 return QCBOR_SUCCESS;
2542 }
2543 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002544 /* Didn't match any of the tag content types */
2545 /* Check the tag for the either case */
2546 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2547 if(uDataType == TagSpec.uTaggedType) {
2548 return QCBOR_SUCCESS;
2549 }
2550 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002551 }
2552
2553 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002554}
2555
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002556
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002557// Semi-private
2558// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002559void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2560 int64_t nLabel,
2561 TagSpecification TagSpec,
2562 QCBORItem *pItem)
2563{
2564 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2565 if(pMe->uLastError != QCBOR_SUCCESS) {
2566 return;
2567 }
2568
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002569 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002570}
2571
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002572// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2574 const char *szLabel,
2575 TagSpecification TagSpec,
2576 QCBORItem *pItem)
2577{
2578 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2579 if(pMe->uLastError != QCBOR_SUCCESS) {
2580 return;
2581 }
2582
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002583 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002584}
2585
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002586// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002587void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2588 int64_t nLabel,
2589 TagSpecification TagSpec,
2590 UsefulBufC *pString)
2591{
2592 QCBORItem Item;
2593 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2594 if(pMe->uLastError == QCBOR_SUCCESS) {
2595 *pString = Item.val.string;
2596 }
2597}
2598
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002599// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002600void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2601 const char * szLabel,
2602 TagSpecification TagSpec,
2603 UsefulBufC *pString)
2604{
2605 QCBORItem Item;
2606 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2607 if(pMe->uLastError == QCBOR_SUCCESS) {
2608 *pString = Item.val.string;
2609 }
2610}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002611
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002612/*
2613Public function, see header qcbor/qcbor_decode.h file
2614*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002615QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2616{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002617 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002618}
2619
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002620/*
2621Public function, see header qcbor/qcbor_decode.h file
2622*/
2623QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2624 QCBORItem *pItemList,
2625 void *pCallbackCtx,
2626 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002627{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002628 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002629}
2630
2631
Laurence Lundblade34691b92020-05-18 22:25:25 -07002632static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002633{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002634 if(pMe->uLastError != QCBOR_SUCCESS) {
2635 // Already in error state; do nothing.
2636 return;
2637 }
2638
2639 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002640 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002641 if(pMe->uLastError != QCBOR_SUCCESS) {
2642 return;
2643 }
2644
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002645 /* Need to get the current pre-order nesting level and cursor to be
2646 at the first item in the map/array just entered.
2647
2648 Also need to current map nesting level and start cursor to
2649 be at the right place.
2650
2651 The UsefulInBuf offset could be anywhere, so no assumption is
2652 made about it.
2653
2654 No assumption is made about the pre-order nesting level either.
2655
2656 However the map mode nesting level is assumed to be one above
2657 the map level that is being entered.
2658 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002659 /* Seek to the data item that is the map or array */
2660 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002661 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002662
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002663 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002664}
2665
2666
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002667/*
2668Public function, see header qcbor/qcbor_decode.h file
2669*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002670void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002671{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002672 QCBORItem OneItemSeach[2];
2673 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2674 OneItemSeach[0].label.int64 = nLabel;
2675 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2676 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002677
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002678 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002679 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002680}
2681
2682
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002683/*
2684Public function, see header qcbor/qcbor_decode.h file
2685*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002686void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002688 QCBORItem OneItemSeach[2];
2689 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2690 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2691 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2692 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002694 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002695}
2696
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002697/*
2698Public function, see header qcbor/qcbor_decode.h file
2699*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002700void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002701{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002702 QCBORItem OneItemSeach[2];
2703 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2704 OneItemSeach[0].label.int64 = nLabel;
2705 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2706 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002707
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002708 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002709}
2710
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002711/*
2712Public function, see header qcbor/qcbor_decode.h file
2713*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002714void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2715{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002716 QCBORItem OneItemSeach[2];
2717 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2718 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2719 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2720 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002722 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002723}
2724
2725
Laurence Lundblade02625d42020-06-25 14:41:41 -07002726// Semi-private function
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002727/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002728void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002729{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002730 if(pMe->uLastError != QCBOR_SUCCESS) {
2731 // Already in error state; do nothing.
2732 return;
2733 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002734
2735 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002736 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002737 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002738 if(pMe->uLastError != QCBOR_SUCCESS) {
2739 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002740 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002741 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002742 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2743 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002744 }
2745
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002746 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002748 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002749 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002750
Laurence Lundblade02625d42020-06-25 14:41:41 -07002751 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002752}
2753
Laurence Lundblade02625d42020-06-25 14:41:41 -07002754
2755/*
2756 This is for exiting a level that is a bounded map, array or bstr
2757 wrapped CBOR. It is the work common to these.
2758
2759 One chunk of work is to set up the pre-order traversal so it is at
2760 the item just after the bounded map, array or bstr that is being
2761 exited. This is somewhat complex.
2762
2763 The other work is to level-up the bounded mode to next higest bounded
2764 mode or the top level if there isn't one.
2765 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002766static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002767ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002768{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002769 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002770
Laurence Lundblade02625d42020-06-25 14:41:41 -07002771 /*
2772 First the pre-order-traversal byte offset is positioned to the
2773 item just after the bounded mode item that was just consumed.
2774 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002775 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2776
Laurence Lundblade02625d42020-06-25 14:41:41 -07002777 /*
2778 Next, set the current nesting level to one above the bounded level
2779 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002780
Laurence Lundblade02625d42020-06-25 14:41:41 -07002781 DecodeNesting_CheckBoundedType() is always called before this and
2782 makes sure pCurrentBounded is valid.
2783 */
2784 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2785
2786 /*
2787 This does the complex work of leveling up the pre-order traversal
2788 when the end of a map or array or another bounded level is
2789 reached. It may do nothing, or ascend all the way to the top
2790 level.
2791 */
2792 uErr = NestLevelAscender(pMe);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002793 if(uErr != QCBOR_SUCCESS) {
2794 goto Done;
2795 }
2796
Laurence Lundblade02625d42020-06-25 14:41:41 -07002797 /*
2798 This makes the next highest bounded level the current bounded
2799 level. If there is no next highest level, then no bounded mode is
2800 in effect.
2801 */
2802 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002803
Laurence Lundblade02625d42020-06-25 14:41:41 -07002804 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002805
2806Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002807 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002808 return uErr;
2809}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002810
Laurence Lundblade02625d42020-06-25 14:41:41 -07002811
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002812// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002813void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002814{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002815 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002817 return;
2818 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002819
Laurence Lundblade02625d42020-06-25 14:41:41 -07002820 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002821
Laurence Lundblade02625d42020-06-25 14:41:41 -07002822 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002823 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2824 goto Done;
2825 }
2826
Laurence Lundblade02625d42020-06-25 14:41:41 -07002827 /*
2828 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002829 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002830 from previous map search, then do a dummy search.
2831 */
2832 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002833 QCBORItem Dummy;
2834 Dummy.uLabelType = QCBOR_TYPE_NONE;
2835 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2836 if(uErr != QCBOR_SUCCESS) {
2837 goto Done;
2838 }
2839 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002840
Laurence Lundblade02625d42020-06-25 14:41:41 -07002841 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002842
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002843Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002844 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002845}
2846
2847
Laurence Lundblade1341c592020-04-11 14:19:05 -07002848void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002849{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002850 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002851 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2852 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002853}
2854
2855
Laurence Lundblade1341c592020-04-11 14:19:05 -07002856
Laurence Lundblade02625d42020-06-25 14:41:41 -07002857static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe,
2858 const QCBORItem *pItem,
2859 uint8_t uTagRequirement,
2860 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002861{
2862 if(pMe->uLastError != QCBOR_SUCCESS) {
2863 // Already in error state; do nothing.
2864 return pMe->uLastError;
2865 }
2866
2867 QCBORError uError = QCBOR_SUCCESS;
2868
2869 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2870 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2871 goto Done;;
2872 }
2873
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002874 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002875 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2876
2877 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2878 if(uError != QCBOR_SUCCESS) {
2879 goto Done;
2880 }
2881
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002882 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
2883 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002884 so the increment in NestLevelAscender called by ExitBoundedLevel()
2885 will work right. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002886 // TODO: method for this
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002887 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2888 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002889
2890 if(pBstr) {
2891 *pBstr = pItem->val.string;
2892 }
2893
2894 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002895
2896 // Need to move UIB input cursor to the right place
2897
2898 // Really this is a subtraction and an assignment; not much code
2899 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002900 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002901
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002902 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002903
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002904
2905 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2906
2907 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002908
Laurence Lundblade02625d42020-06-25 14:41:41 -07002909 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2910 uPreviousLength,
2911 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002912Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002913 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002914
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002915 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002916}
2917
2918
Laurence Lundblade02625d42020-06-25 14:41:41 -07002919/*
2920 Public function, see header qcbor/qcbor_decode.h file
2921 */
2922void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
2923 uint8_t uTagRequirement,
2924 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002925{
2926 if(pMe->uLastError != QCBOR_SUCCESS) {
2927 // Already in error state; do nothing.
2928 return;
2929 }
2930
2931 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002932 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002933 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2934 if(pMe->uLastError != QCBOR_SUCCESS) {
2935 return;
2936 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002937
Laurence Lundblade02625d42020-06-25 14:41:41 -07002938 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe,
2939 &Item,
2940 uTagRequirement,
2941 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002942}
2943
2944
Laurence Lundblade02625d42020-06-25 14:41:41 -07002945/*
2946 Public function, see header qcbor/qcbor_decode.h file
2947 */
2948void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2949 uint8_t uTagRequirement,
2950 int64_t nLabel,
2951 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002952{
2953 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002954 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002955
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002956 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002957}
2958
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002959
Laurence Lundblade02625d42020-06-25 14:41:41 -07002960/*
2961 Public function, see header qcbor/qcbor_decode.h file
2962 */
2963void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
2964 uint8_t uTagRequirement,
2965 const char *szLabel,
2966 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002967{
2968 QCBORItem Item;
2969 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2970
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002971 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002972}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002973
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002974
Laurence Lundblade02625d42020-06-25 14:41:41 -07002975/*
2976 Public function, see header qcbor/qcbor_decode.h file
2977 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002978void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002979{
Laurence Lundblade02625d42020-06-25 14:41:41 -07002980 if(pMe->uLastError != QCBOR_SUCCESS) {
2981 // Already in error state; do nothing.
2982 return;
2983 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002984
Laurence Lundblade02625d42020-06-25 14:41:41 -07002985 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2986 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
2987 return;
2988 }
2989
2990 /*
2991 Reset the length of the UsefulInputBuf to what it was before
2992 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002993 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002994 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
2995 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002996
2997
Laurence Lundblade02625d42020-06-25 14:41:41 -07002998 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002999 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003000}
3001
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003002
Laurence Lundbladee6430642020-03-14 21:15:44 -07003003
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003004
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003005
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003006
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003007
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003008
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003009static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3010{
3011 switch(pItem->uDataType) {
3012 case QCBOR_TYPE_TRUE:
3013 *pBool = true;
3014 return QCBOR_SUCCESS;
3015 break;
3016
3017 case QCBOR_TYPE_FALSE:
3018 *pBool = false;
3019 return QCBOR_SUCCESS;
3020 break;
3021
3022 default:
3023 return QCBOR_ERR_UNEXPECTED_TYPE;
3024 break;
3025 }
3026}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003027
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003028/*
3029Public function, see header qcbor/qcbor_decode.h file
3030*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003031void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003032{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003033 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003034 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003035 return;
3036 }
3037
Laurence Lundbladec4537442020-04-14 18:53:22 -07003038 QCBORError nError;
3039 QCBORItem Item;
3040
3041 nError = QCBORDecode_GetNext(pMe, &Item);
3042 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003043 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003044 return;
3045 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003046 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003047}
3048
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003049/*
3050Public function, see header qcbor/qcbor_decode.h file
3051*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003052void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003053{
3054 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003055 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003056
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003057 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003058}
3059
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003060/*
3061Public function, see header qcbor/qcbor_decode.h file
3062*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003063void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3064{
3065 QCBORItem Item;
3066 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3067
3068 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3069}
3070
3071
3072
3073void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003074{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003075 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003076 // Already in error state, do nothing
3077 return;
3078 }
3079
3080 QCBORError nError;
3081 QCBORItem Item;
3082
3083 nError = QCBORDecode_GetNext(pMe, &Item);
3084 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003085 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003086 return;
3087 }
3088
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003089 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3090
3091 if(pMe->uLastError == QCBOR_SUCCESS) {
3092 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003093 }
3094}
3095
Laurence Lundbladec4537442020-04-14 18:53:22 -07003096
3097
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003098
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003099static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003100{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003101 *pbIsNegative = false;
3102
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003103 bool bMustBeTagged = true; // TODO: fix this --- they have to tell us if they are expecting positive or negative
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003104
3105 switch(pItem->uDataType) {
3106 case QCBOR_TYPE_BYTE_STRING:
3107 // TODO: check that there is no tag here?
3108 if(bMustBeTagged) {
3109 return QCBOR_ERR_UNEXPECTED_TYPE;
3110 } else {
3111 *pValue = pItem->val.string;
3112 return QCBOR_SUCCESS;
3113 }
3114 break;
3115
3116 case QCBOR_TYPE_POSBIGNUM:
3117 *pValue = pItem->val.string;
3118 return QCBOR_SUCCESS;
3119 break;
3120
3121 case QCBOR_TYPE_NEGBIGNUM:
3122 *pbIsNegative = true;
3123 *pValue = pItem->val.string;
3124 return QCBOR_SUCCESS;
3125 break;
3126
3127 default:
3128 return QCBOR_ERR_UNEXPECTED_TYPE;
3129 break;
3130 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003131}
3132
3133
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003134/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003135 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3136 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3137 will always be false on the asumption that it is positive, but it can be interpretted as
3138 negative if the the sign is know from other context.
3139 @param[out] pValue The bytes that make up the big num
3140 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3141
3142 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3143 a positive big num or a negative big num.
3144
3145 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003146void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003147{
3148 if(pMe->uLastError != QCBOR_SUCCESS) {
3149 // Already in error state, do nothing
3150 return;
3151 }
3152
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003153 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003154 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3155 if(uError != QCBOR_SUCCESS) {
3156 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003157 return;
3158 }
3159
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003160 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003161}
3162
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003163/*
3164Public function, see header qcbor/qcbor_decode.h file
3165*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003166void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003167{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003168 QCBORItem Item;
3169 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003170
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003171 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003172}
3173
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003174/*
3175Public function, see header qcbor/qcbor_decode.h file
3176*/
3177void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3178{
3179 QCBORItem Item;
3180 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3181
3182 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3183}
3184
3185
3186
3187// Semi private
3188QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3189{
3190 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3191 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3192
3193 QCBORError uReturn;
3194
3195 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3196 *pMessage = pItem->val.string;
3197 if(pbIsNot7Bit != NULL) {
3198 *pbIsNot7Bit = false;
3199 }
3200 uReturn = QCBOR_SUCCESS;
3201 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3202 *pMessage = pItem->val.string;
3203 if(pbIsNot7Bit != NULL) {
3204 *pbIsNot7Bit = true;
3205 }
3206 uReturn = QCBOR_SUCCESS;
3207
3208 } else {
3209 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3210 }
3211
3212 return uReturn;
3213}
3214
3215
3216
3217
3218
Laurence Lundbladec4537442020-04-14 18:53:22 -07003219
3220
3221
Laurence Lundbladee6430642020-03-14 21:15:44 -07003222
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003223typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003224
3225
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003226// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003227static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003228{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003229 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003230
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003231 if(uResult != 0) {
3232 /* This loop will run a maximum of 19 times because
3233 * UINT64_MAX < 10 ^^ 19. More than that will cause
3234 * exit with the overflow error
3235 */
3236 for(; nExponent > 0; nExponent--) {
3237 if(uResult > UINT64_MAX / 10) {
3238 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3239 }
3240 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003241 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003242
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003243 for(; nExponent < 0; nExponent++) {
3244 uResult = uResult / 10;
3245 if(uResult == 0) {
3246 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3247 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003248 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003249 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003250 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003251
3252 *puResult = uResult;
3253
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003254 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003255}
3256
3257
Laurence Lundbladee6430642020-03-14 21:15:44 -07003258/* Convert a decimal fraction to an int64_t without using
3259 floating point or math libraries. Most decimal fractions
3260 will not fit in an int64_t and this will error out with
3261 under or overflow
3262 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003263static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003264{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003265 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003266
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003267 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003268
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003269 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003270 * INT64_MAX < 2^31. More than that will cause
3271 * exist with the overflow error
3272 */
3273 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003274 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003275 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003276 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003277 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003278 nExponent--;
3279 }
3280
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003281 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003282 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003283 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3284 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003285 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003286 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003287 }
3288
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003289 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003290
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003291 return QCBOR_SUCCESS;
3292}
3293
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003294/*
3295 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3296 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003297static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3298{
3299 uint64_t uResult;
3300
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003301 // Take the absolute value of the mantissa and convert to unsigned.
3302 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003303 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3304
3305 // Do the exponentiation of the positive mantissa
3306 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3307 if(uReturn) {
3308 return uReturn;
3309 }
3310
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003311
Laurence Lundblade983500d2020-05-14 11:49:34 -07003312 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3313 of INT64_MIN. This assumes two's compliment representation where
3314 INT64_MIN is one increment farther from 0 than INT64_MAX.
3315 Trying to write -INT64_MIN doesn't work to get this because the
3316 compiler tries to work with an int64_t which can't represent
3317 -INT64_MIN.
3318 */
3319 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3320
3321 // Error out if too large
3322 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003323 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3324 }
3325
3326 // Casts are safe because of checks above
3327 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3328
3329 return QCBOR_SUCCESS;
3330}
3331
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003332/*
3333 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3334 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003335static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3336{
3337 if(nMantissa < 0) {
3338 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3339 }
3340
3341 // Cast to unsigned is OK because of check for negative
3342 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3343 // Exponentiation is straight forward
3344 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3345}
3346
3347
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003348#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003349
3350
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003351static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003352{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003353 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003354
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003355 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003356 const uint8_t *pByte = BigNum.ptr;
3357 size_t uLen = BigNum.len;
3358 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003359 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003360 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003361 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003362 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003363 }
3364
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003365 *pResult = uResult;
3366 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003367}
3368
Laurence Lundblade887add82020-05-17 05:50:34 -07003369static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003370{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003371 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003372}
3373
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003374static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003375{
3376 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003377 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3378 if(uError) {
3379 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003380 }
3381 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3382 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003383 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003384}
3385
3386
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003387static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003388{
3389 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003390 /* negaative int furthest from zero is INT64_MIN
3391 which is expressed as -INT64_MAX-1. The value of
3392 a negative bignum is -n-1, one further from zero
3393 than the positive bignum */
3394
3395 /* say INT64_MIN is -2; then INT64_MAX is 1.
3396 Then -n-1 <= INT64_MIN.
3397 Then -n -1 <= -INT64_MAX - 1
3398 THen n <= INT64_MAX. */
3399 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003400 if(uError) {
3401 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003402 }
3403 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003404 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003405 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003406 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003407 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408}
3409
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003410#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003411
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003412
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003413/*
3414Convert a integers and floats to an int64_t.
3415
3416\param[in] uOptions Bit mask list of conversion options.
3417
3418\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3419
3420\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3421
3422\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3423
3424*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003425static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3426{
3427 switch(pItem->uDataType) {
3428 // TODO: float when ifdefs are set
3429 case QCBOR_TYPE_DOUBLE:
3430 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3431 // TODO: what about under/overflow here?
3432 // Invokes the floating-point HW and/or compiler-added libraries
3433 feclearexcept(FE_ALL_EXCEPT);
3434 *pnValue = llround(pItem->val.dfnum);
3435 if(fetestexcept(FE_INVALID)) {
3436 // TODO: better error code
3437 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3438 }
3439 } else {
3440 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3441 }
3442 break;
3443
3444 case QCBOR_TYPE_INT64:
3445 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3446 *pnValue = pItem->val.int64;
3447 } else {
3448 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3449 }
3450 break;
3451
3452 case QCBOR_TYPE_UINT64:
3453 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3454 if(pItem->val.uint64 < INT64_MAX) {
3455 *pnValue = pItem->val.int64;
3456 } else {
3457 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3458 }
3459 } else {
3460 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3461 }
3462 break;
3463
3464 default:
3465 return QCBOR_ERR_UNEXPECTED_TYPE;
3466 }
3467 return QCBOR_SUCCESS;
3468}
3469
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003470
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003471void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3472 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003473 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003474 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003475{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003476 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003477 return;
3478 }
3479
Laurence Lundbladee6430642020-03-14 21:15:44 -07003480 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003481 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3482 if(uError) {
3483 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484 return;
3485 }
3486
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003487 if(pItem) {
3488 *pItem = Item;
3489 }
3490
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003491 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003492}
3493
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003494
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003495void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3496 int64_t nLabel,
3497 uint32_t uOptions,
3498 int64_t *pnValue,
3499 QCBORItem *pItem)
3500{
3501 QCBORItem Item;
3502 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3503
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003504 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003505}
3506
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003507
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003508void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3509 const char * szLabel,
3510 uint32_t uOptions,
3511 int64_t *pnValue,
3512 QCBORItem *pItem)
3513{
3514 if(pMe->uLastError != QCBOR_SUCCESS) {
3515 return;
3516 }
3517
3518 QCBORItem Item;
3519 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3520
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003521 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003522}
3523
3524
3525
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003526/*
3527 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003528
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003529 \param[in] uOptions Bit mask list of conversion options.
3530
3531 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3532
3533 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3534
3535 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3536
3537 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003538static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3539{
3540 QCBORError uErr;
3541
3542 switch(pItem->uDataType) {
3543
3544 case QCBOR_TYPE_POSBIGNUM:
3545 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3546 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003547 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003548 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003549 }
3550 break;
3551
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003552 case QCBOR_TYPE_NEGBIGNUM:
3553 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3554 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003555 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003556 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003557 }
3558 break;
3559
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003560#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3561 case QCBOR_TYPE_DECIMAL_FRACTION:
3562 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3563 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3564 pItem->val.expAndMantissa.nExponent,
3565 pnValue,
3566 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003567 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003568 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3569 }
3570 break;
3571
3572 case QCBOR_TYPE_BIGFLOAT:
3573 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3574 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3575 pItem->val.expAndMantissa.nExponent,
3576 pnValue,
3577 Exponentitate2);
3578 } else {
3579 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3580 }
3581 break;
3582
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3584 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3585 int64_t nMantissa;
3586 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3587 if(uErr) {
3588 return uErr;
3589 }
3590 return ExponentiateNN(nMantissa,
3591 pItem->val.expAndMantissa.nExponent,
3592 pnValue,
3593 Exponentitate10);
3594 } else {
3595 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3596 }
3597 break;
3598
3599 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3600 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3601 int64_t nMantissa;
3602 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3603 if(uErr) {
3604 return uErr;
3605 }
3606 return ExponentiateNN(nMantissa,
3607 pItem->val.expAndMantissa.nExponent,
3608 pnValue,
3609 Exponentitate10);
3610 } else {
3611 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3612 }
3613 break;
3614
3615 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3616 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3617 int64_t nMantissa;
3618 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3619 if(uErr) {
3620 return uErr;
3621 }
3622 return ExponentiateNN(nMantissa,
3623 pItem->val.expAndMantissa.nExponent,
3624 pnValue,
3625 Exponentitate2);
3626 } else {
3627 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3628 }
3629 break;
3630
3631 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3632 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3633 int64_t nMantissa;
3634 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3635 if(uErr) {
3636 return uErr;
3637 }
3638 return ExponentiateNN(nMantissa,
3639 pItem->val.expAndMantissa.nExponent,
3640 pnValue,
3641 Exponentitate2);
3642 } else {
3643 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003644 }
3645 break;
3646
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003648 return QCBOR_ERR_UNEXPECTED_TYPE;
3649#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003650 }
3651}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003652
3653
Laurence Lundbladec4537442020-04-14 18:53:22 -07003654/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003655 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003656 */
3657void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003658{
3659 QCBORItem Item;
3660
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003661 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003662
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003663 if(pMe->uLastError == QCBOR_SUCCESS) {
3664 // The above conversion succeeded
3665 return;
3666 }
3667
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003668 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003669 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003670 return;
3671 }
3672
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003673 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003674}
3675
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003676
3677/*
3678Public function, see header qcbor/qcbor_decode.h file
3679*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003680void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3681{
3682 QCBORItem Item;
3683
3684 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3685
3686 if(pMe->uLastError == QCBOR_SUCCESS) {
3687 // The above conversion succeeded
3688 return;
3689 }
3690
3691 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3692 // The above conversion failed in a way that code below can't correct
3693 return;
3694 }
3695
3696 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3697}
3698
3699
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003700/*
3701Public function, see header qcbor/qcbor_decode.h file
3702*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003703void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3704{
3705 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003706 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3707
3708 if(pMe->uLastError == QCBOR_SUCCESS) {
3709 // The above conversion succeeded
3710 return;
3711 }
3712
3713 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3714 // The above conversion failed in a way that code below can't correct
3715 return;
3716 }
3717
3718 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3719}
3720
3721
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003722static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3723{
3724 switch(pItem->uDataType) {
3725 // TODO: type flaot
3726 case QCBOR_TYPE_DOUBLE:
3727 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3728 feclearexcept(FE_ALL_EXCEPT);
3729 double dRounded = round(pItem->val.dfnum);
3730 // TODO: over/underflow
3731 if(fetestexcept(FE_INVALID)) {
3732 // TODO: better error code
3733 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3734 } else if(isnan(dRounded)) {
3735 // TODO: better error code
3736 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3737 } else if(dRounded >= 0) {
3738 *puValue = (uint64_t)dRounded;
3739 } else {
3740 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3741 }
3742 } else {
3743 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3744 }
3745 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003746
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003747 case QCBOR_TYPE_INT64:
3748 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3749 if(pItem->val.int64 >= 0) {
3750 *puValue = (uint64_t)pItem->val.int64;
3751 } else {
3752 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3753 }
3754 } else {
3755 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3756 }
3757 break;
3758
3759 case QCBOR_TYPE_UINT64:
3760 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3761 *puValue = pItem->val.uint64;
3762 } else {
3763 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3764 }
3765 break;
3766
3767 default:
3768 return QCBOR_ERR_UNEXPECTED_TYPE;
3769 }
3770 return QCBOR_SUCCESS;
3771}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003772
3773
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003774void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3775 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003776 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003777 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003778{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003779 if(pMe->uLastError != QCBOR_SUCCESS) {
3780 return;
3781 }
3782
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003784
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003785 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3786 if(uError) {
3787 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003788 return;
3789 }
3790
Laurence Lundbladea826c502020-05-10 21:07:00 -07003791 if(pItem) {
3792 *pItem = Item;
3793 }
3794
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003795 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003796}
3797
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003798
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003799void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3800{
3801 int64_t uValue;
3802 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3803 if(pMe->uLastError != QCBOR_SUCCESS) {
3804 return;
3805 }
3806
3807 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3808 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3809 }
3810}
3811
3812void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3813{
3814 int64_t uValue;
3815 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3816 if(pMe->uLastError != QCBOR_SUCCESS) {
3817 return;
3818 }
3819
3820 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3821 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3822 }
3823}
3824
3825void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3826{
3827 int64_t uValue;
3828 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3829 if(pMe->uLastError != QCBOR_SUCCESS) {
3830 return;
3831 }
3832
3833 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3834 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3835 }
3836}
3837
3838
3839
3840
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003841void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3842 int64_t nLabel,
3843 uint32_t uOptions,
3844 uint64_t *puValue,
3845 QCBORItem *pItem)
3846{
3847 QCBORItem Item;
3848 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3849
3850 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3851}
3852
3853
3854void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3855 const char * szLabel,
3856 uint32_t uOptions,
3857 uint64_t *puValue,
3858 QCBORItem *pItem)
3859{
3860 if(pMe->uLastError != QCBOR_SUCCESS) {
3861 return;
3862 }
3863
3864 QCBORItem Item;
3865 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3866
3867 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3868}
3869
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003870/*
3871 Public function, see header qcbor/qcbor_decode.h file
3872*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003873static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3874{
3875 QCBORError uErr;
3876
3877 switch(pItem->uDataType) {
3878
3879 case QCBOR_TYPE_POSBIGNUM:
3880 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3881 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3882 } else {
3883 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3884 }
3885 break;
3886
3887 case QCBOR_TYPE_NEGBIGNUM:
3888 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3889 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3890 } else {
3891 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3892 }
3893 break;
3894
3895#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3896
3897 case QCBOR_TYPE_DECIMAL_FRACTION:
3898 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3899 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3900 pItem->val.expAndMantissa.nExponent,
3901 puValue,
3902 Exponentitate10);
3903 } else {
3904 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3905 }
3906 break;
3907
3908 case QCBOR_TYPE_BIGFLOAT:
3909 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3910 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3911 pItem->val.expAndMantissa.nExponent,
3912 puValue,
3913 Exponentitate2);
3914 } else {
3915 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3916 }
3917 break;
3918
3919 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3920 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3921 // TODO: Would be better to convert to unsigned
3922 int64_t nMantissa;
3923 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3924 if(uErr != QCBOR_SUCCESS) {
3925 return uErr;
3926 }
3927 return ExponentitateNU(nMantissa,
3928 pItem->val.expAndMantissa.nExponent,
3929 puValue,
3930 Exponentitate10);
3931 } else {
3932 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3933 }
3934 break;
3935
3936 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3937 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3938 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3939 } else {
3940 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3941 }
3942 break;
3943
3944 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3945 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3946 // TODO: Would be better to convert to unsigned
3947 int64_t nMantissa;
3948 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3949 if(uErr != QCBOR_SUCCESS) {
3950 return uErr;
3951 }
3952 return ExponentitateNU(nMantissa,
3953 pItem->val.expAndMantissa.nExponent,
3954 puValue,
3955 Exponentitate2);
3956 } else {
3957 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3958 }
3959 break;
3960
3961 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3962 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3963 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3964 } else {
3965 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3966 }
3967 break;
3968#endif
3969 default:
3970 return QCBOR_ERR_UNEXPECTED_TYPE;
3971 }
3972}
3973
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003974/*
3975 Public function, see header qcbor/qcbor_decode.h file
3976*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003977void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003978{
3979 QCBORItem Item;
3980
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003981 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003982
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003983 if(pMe->uLastError == QCBOR_SUCCESS) {
3984 // The above conversion succeeded
3985 return;
3986 }
3987
3988 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3989 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003990 return;
3991 }
3992
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003993 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003994}
3995
Laurence Lundbladec4537442020-04-14 18:53:22 -07003996
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003997/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003998 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003999*/
4000void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4001{
4002 QCBORItem Item;
4003
4004 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4005
4006 if(pMe->uLastError == QCBOR_SUCCESS) {
4007 // The above conversion succeeded
4008 return;
4009 }
4010
4011 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4012 // The above conversion failed in a way that code below can't correct
4013 return;
4014 }
4015
4016 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4017}
4018
4019
4020/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004021 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004022*/
4023void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4024{
4025 QCBORItem Item;
4026 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4027
4028 if(pMe->uLastError == QCBOR_SUCCESS) {
4029 // The above conversion succeeded
4030 return;
4031 }
4032
4033 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4034 // The above conversion failed in a way that code below can't correct
4035 return;
4036 }
4037
4038 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4039}
4040
4041
4042static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4043{
4044 switch(pItem->uDataType) {
4045 // TODO: float when ifdefs are set
4046 case QCBOR_TYPE_DOUBLE:
4047 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4048 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4049 *pdValue = pItem->val.dfnum;
4050 } else {
4051 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4052 }
4053 }
4054 break;
4055
4056 case QCBOR_TYPE_INT64:
4057 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4058 // TODO: how does this work?
4059 *pdValue = (double)pItem->val.int64;
4060
4061 } else {
4062 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4063 }
4064 break;
4065
4066 case QCBOR_TYPE_UINT64:
4067 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4068 *pdValue = (double)pItem->val.uint64;
4069 } else {
4070 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4071 }
4072 break;
4073
4074 default:
4075 return QCBOR_ERR_UNEXPECTED_TYPE;
4076 }
4077
4078 return QCBOR_SUCCESS;
4079}
4080
4081
4082
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004083void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4084 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004085 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004086 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004087{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004088 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004089 return;
4090 }
4091
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004092 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004093
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004094 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004095 if(uError) {
4096 pMe->uLastError = (uint8_t)uError;
4097 return;
4098 }
4099
4100 if(pItem) {
4101 *pItem = Item;
4102 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004103
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004104 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004105}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004106
Laurence Lundbladec4537442020-04-14 18:53:22 -07004107
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004108void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4109 int64_t nLabel,
4110 uint32_t uOptions,
4111 double *pdValue,
4112 QCBORItem *pItem)
4113{
4114 QCBORItem Item;
4115 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4116
4117 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4118}
4119
4120void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4121 const char * szLabel,
4122 uint32_t uOptions,
4123 double *pdValue,
4124 QCBORItem *pItem)
4125{
4126 if(pMe->uLastError != QCBOR_SUCCESS) {
4127 return;
4128 }
4129
4130 QCBORItem Item;
4131 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4132
4133 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4134}
4135
4136
4137
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004138static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4139{
4140 double dResult;
4141
4142 dResult = 0.0;
4143 const uint8_t *pByte = BigNum.ptr;
4144 size_t uLen = BigNum.len;
4145 /* This will overflow and become the float value INFINITY if the number
4146 is too large to fit. No error will be logged.
4147 TODO: should an error be logged? */
4148 while(uLen--) {
4149 dResult = (dResult * 256.0) + (double)*pByte++;
4150 }
4151
4152 return dResult;
4153}
4154
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004155static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004156{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004157 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004158 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4159
4160 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004161 switch(pItem->uDataType) {
4162 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004163
4164#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004165 case QCBOR_TYPE_DECIMAL_FRACTION:
4166 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4167 // TODO: rounding and overflow errors
4168 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4169 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4170 } else {
4171 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4172 }
4173 break;
4174
4175 case QCBOR_TYPE_BIGFLOAT:
4176 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4177 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4178 exp2((double)pItem->val.expAndMantissa.nExponent);
4179 } else {
4180 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4181 }
4182 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004183#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004184
4185 case QCBOR_TYPE_POSBIGNUM:
4186 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4187 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4188 } else {
4189 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4190 }
4191 break;
4192
4193 case QCBOR_TYPE_NEGBIGNUM:
4194 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004195 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004196 } else {
4197 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4198 }
4199 break;
4200
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004201#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004202 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4203 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4204 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4205 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4206 } else {
4207 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4208 }
4209 break;
4210
4211 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4212 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4213 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4214 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4215 } else {
4216 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4217 }
4218 break;
4219
4220 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4221 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4222 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4223 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4224 } else {
4225 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4226 }
4227 break;
4228
4229 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4230 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004231 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004232 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4233 } else {
4234 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4235 }
4236 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004237#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4238
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004239
4240 default:
4241 return QCBOR_ERR_UNEXPECTED_TYPE;
4242 }
4243
4244 return QCBOR_SUCCESS;
4245}
4246
4247
4248/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004249 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004250*/
4251void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4252{
4253
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004254 QCBORItem Item;
4255
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004256 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004257
4258 if(pMe->uLastError == QCBOR_SUCCESS) {
4259 // The above conversion succeeded
4260 return;
4261 }
4262
4263 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4264 // The above conversion failed in a way that code below can't correct
4265 return;
4266 }
4267
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004268 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004269}
4270
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004271
4272/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004273 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004274*/
4275void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4276{
4277 QCBORItem Item;
4278
4279 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4280
4281 if(pMe->uLastError == QCBOR_SUCCESS) {
4282 // The above conversion succeeded
4283 return;
4284 }
4285
4286 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4287 // The above conversion failed in a way that code below can't correct
4288 return;
4289 }
4290
4291 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4292}
4293
4294
4295/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004296 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004297*/
4298void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4299{
4300 QCBORItem Item;
4301 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4302
4303 if(pMe->uLastError == QCBOR_SUCCESS) {
4304 // The above conversion succeeded
4305 return;
4306 }
4307
4308 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4309 // The above conversion failed in a way that code below can't correct
4310 return;
4311 }
4312
4313 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4314}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004315
4316
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004317#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004318void FarfDecimalFraction(QCBORDecodeContext *pMe,
4319 uint8_t uTagRequirement,
4320 QCBORItem *pItem,
4321 int64_t *pnMantissa,
4322 int64_t *pnExponent)
4323{
4324 QCBORError uErr;
4325
4326 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4327 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4328 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4329 return;
4330 }
4331 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4332 if(uErr != QCBOR_SUCCESS) {
4333 pMe->uLastError = (uint8_t)uErr;
4334 return;
4335 }
4336 }
4337
4338 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4339 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4340 return;
4341 }
4342
4343 switch (pItem->uDataType) {
4344
4345 case QCBOR_TYPE_DECIMAL_FRACTION:
4346 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4347 *pnExponent = pItem->val.expAndMantissa.nExponent;
4348 break;
4349
4350 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4351 *pnExponent = pItem->val.expAndMantissa.nExponent;
4352
4353 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4354 if(uErr != QCBOR_SUCCESS) {
4355 pMe->uLastError = (uint8_t)uErr;
4356 }
4357 break;
4358
4359 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4360 *pnExponent = pItem->val.expAndMantissa.nExponent;
4361
4362 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4363 if(uErr != QCBOR_SUCCESS) {
4364 pMe->uLastError = (uint8_t)uErr;
4365 }
4366 break;
4367
4368 default:
4369 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4370 }
4371}
4372
4373void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4374 uint8_t uTagRequirement,
4375 int64_t nLabel,
4376 int64_t *pnMantissa,
4377 int64_t *pnExponent)
4378{
4379 QCBORItem Item;
4380
4381 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4382 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4383}
4384
4385
4386
4387void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4388 uint8_t uTagRequirement,
4389 const char *szLabel,
4390 int64_t *pnMantissa,
4391 int64_t *pnExponent)
4392{
4393 QCBORItem Item;
4394
4395 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4396
4397 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4398}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004399#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004400
4401
4402UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4403{
4404 while(uInt & 0xff0000000000UL) {
4405 uInt = uInt << 8;
4406 };
4407
4408 UsefulOutBuf UOB;
4409
4410 UsefulOutBuf_Init(&UOB, Buffer);
4411
4412 while(uInt) {
4413 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4414 uInt = uInt << 8;
4415 }
4416
4417 return UsefulOutBuf_OutUBuf(&UOB);
4418}
4419
4420
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004421#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4422
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004423void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4424 uint8_t uTagRequirement,
4425 int64_t nLabel,
4426 UsefulBuf pBufferForMantissa,
4427 UsefulBufC *pMantissa,
4428 bool *pbIsNegative,
4429 int64_t *pnExponent)
4430{
4431 QCBORItem Item;
4432 QCBORError uErr;
4433
4434 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4435
4436 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4437 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4438 if(uErr != QCBOR_SUCCESS) {
4439 pMe->uLastError = (uint8_t)uErr;
4440 return;
4441 }
4442 }
4443
4444 uint64_t uMantissa;
4445
4446 switch (Item.uDataType) {
4447
4448 case QCBOR_TYPE_DECIMAL_FRACTION:
4449 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4450 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4451 *pbIsNegative = false;
4452 } else {
4453 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4454 *pbIsNegative = true;
4455 }
4456 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4457 *pnExponent = Item.val.expAndMantissa.nExponent;
4458 break;
4459
4460 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4461 *pnExponent = Item.val.expAndMantissa.nExponent;
4462 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4463 *pbIsNegative = false;
4464 break;
4465
4466 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4467 *pnExponent = Item.val.expAndMantissa.nExponent;
4468 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4469 *pbIsNegative = true;
4470 break;
4471
4472 default:
4473 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4474 }
4475}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004476#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */