blob: 281f9e2ce5280c594196c7539cd147cd17e7b241 [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_IsDefiniteLength(const QCBORDecodeNesting *pNesting)
179{
180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
181 /* Not a map or array */
182 return false;
183 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700184 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185 /* Is indefinite */
186 return false;
187 }
188 /* All checks passed; is a definte length map or array */
189 return true;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundblade642282a2020-06-23 12:00:33 -0700193inline static bool
194DecodeNesting_IsBstrWrapped(const QCBORDecodeNesting *pNesting)
195{
196 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
197 /* is a byte string */
198 return true;
199 }
200 return false;
201}
202
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700203
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700204inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205{
206 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
207 return true;
208 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700209 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210 return true;
211 }
212 return false;
213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundblade02625d42020-06-25 14:41:41 -0700216inline static void DecodeNesting_SetMapOrArrayBoundedMode(const QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700217{
218 // Should be only called on maps and arrays
219 // TODO: check this cast, maybe give an error?
220 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
221}
222
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700223
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224inline static void DecodeNesting_ClearBoundedMode(const QCBORDecodeNesting *pNesting)
225{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700226 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700227}
228
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700229
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700230inline static bool
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231DecodeNesting_IsAtEndOfBoundedFarf(const QCBORDecodeNesting *pNesting)
232{
233 if(pNesting->pCurrentBounded == NULL) {
234 /* No bounded map or array or... set up. */
235 return false;
236 }
237 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
238 /* Not a map or array */
239 return false;
240 }
241 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
242 /* Not in bounded mode. */
243 return false;
244 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700245
246 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700247 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
248 /* Count is not zero, still unconsumed items. */
249 return false;
250 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700251
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700252 /* All checks passed, got to the end of a definite length map or array */
253 return true;
254}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700255
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256inline static bool
257DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
258{
259 /* Must only be called on map / array; TODO: add checks? */
260 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
261 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700262 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700263 return false;
264 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700265}
266
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700267
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268inline static bool
269DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700270{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700271 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
272 return true;
273 } else {
274 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700275 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700276}
277
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700278
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700279inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700280DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700281{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700283 return false;
284 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700285
286 if(pNesting->pCurrentBounded->uLevelType != uType) {
287 return false;
288 }
289
290 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700291}
292
Laurence Lundblade02625d42020-06-25 14:41:41 -0700293
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700294inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700295DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700296{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700297 /* Only call on array / map; TODO: add check?*/
298 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700299}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700300
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700301
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700302inline static void
303DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
304{
305 pNesting->pCurrent--;
306}
307
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308
309static QCBORError
310DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
311{
312 // Error out if nesting is too deep
313 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
314 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
315 }
316
317 // The actual descend
318 pNesting->pCurrent++;
319
320 pNesting->pCurrent->uLevelType = uType;
321
322 return QCBOR_SUCCESS;
323}
324
325
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700326inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700327DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700328{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700329 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
330 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700331 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700332}
333
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700334
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700335inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700336DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700337 uint8_t uQCBORType,
338 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700340 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341
342 if(uCount == 0) {
343 // Nothing to do for empty definite lenth arrays. They are just are
344 // effectively the same as an item that is not a map or array
345 goto Done;
346 // Empty indefinite length maps and arrays are handled elsewhere
347 }
348
349 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
351 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
352 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700353 goto Done;
354 }
355
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
357 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358 goto Done;
359 }
360
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700362 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
363 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700364
365 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700366
367Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700368 return uError;;
369}
370
371
372static inline void
373DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
374{
375 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
376}
377
378
379static inline void
380DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
381{
382 while(pNesting->pCurrentBounded != &(pNesting->pMapsAndArrays[0])) {
383 pNesting->pCurrentBounded--;
384 if(DecodeNesting_IsCurrentBounded(pNesting)) {
385 break;
386 }
387 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700388}
389
390
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700391inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700392DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
393 size_t uEndOffset,
394 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700395{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700396 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700397
Laurence Lundblade02625d42020-06-25 14:41:41 -0700398 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
399 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700400 goto Done;
401 }
402
Laurence Lundblade02625d42020-06-25 14:41:41 -0700403 // Fill in the new byte string level
404 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700406 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700409 pNesting->pCurrentBounded = pNesting->pCurrent;
410
411Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 return uError;;
413}
414
Laurence Lundbladed0304932020-06-27 10:59:38 -0700415
416static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417DecodeNesting_ZeroDefiniteLengthCount(QCBORDecodeNesting *pNesting)
418{
419 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700420}
421
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700422
Laurence Lundbladeee851742020-01-08 08:37:05 -0800423inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700425{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427 pNesting->pMapsAndArrays[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700428 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
429}
430
431
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700432inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700433DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700434{
435 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700436 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700437
Laurence Lundbladed0304932020-06-27 10:59:38 -0700438 //if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700439 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladed0304932020-06-27 10:59:38 -0700440 //}
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700441}
442
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443static inline void
444DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700445{
446 *pNesting = *pSave;
447}
448
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700449
Laurence Lundblade02625d42020-06-25 14:41:41 -0700450static inline uint32_t
451DecodeNesting_GetEndOfBstr(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452{
453 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
454}
455
456
Laurence Lundblade02625d42020-06-25 14:41:41 -0700457static inline uint32_t
458DecodeNesting_GetPreviousBoundedEnd(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459{
460 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
461}
462
463
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700465
466const char *TypeStr(uint8_t type)
467{
468 switch(type) {
469 case QCBOR_TYPE_MAP: return " map";
470 case QCBOR_TYPE_ARRAY: return "array";
471 case QCBOR_TYPE_BYTE_STRING: return " bstr";
472 default: return " --- ";
473 }
474}
475
476static char buf[20]; // Not thread safe, but that is OK
477const char *CountString(uint16_t uCount, uint16_t uTotal)
478{
479 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
480 strcpy(buf, "indefinite");
481 } else {
482 sprintf(buf, "%d/%d", uCount, uTotal);
483 }
484 return buf;
485}
486
Laurence Lundblade02625d42020-06-25 14:41:41 -0700487void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700488{
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700489 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700490 szName,
491 (uint32_t)pBuf->cursor,
492 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700493
494 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
496 if(&(pNesting->pMapsAndArrays[i]) > pNesting->pCurrent) {
497 break;
498 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700499
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700500 printf("%2s %2d %s ",
501 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
502 i,
503 TypeStr(pNesting->pMapsAndArrays[i].uLevelType));
504
505 if(pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
506 printf(" %5d %5d",
507 pNesting->pMapsAndArrays[i].u.bs.uEndOfBstr,
508 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset);
509
510 } else {
511 printf("%10.10s ",
512 CountString(pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
513 pNesting->pMapsAndArrays[i].u.ma.uCountTotal));
514 if(pNesting->pMapsAndArrays[i].u.ma.uStartOffset != UINT32_MAX) {
515 printf("Bounded start: %u",pNesting->pMapsAndArrays[i].u.ma.uStartOffset);
516 }
517 }
518
519 printf("\n");
520 /*
521 TYPE
522 count/total
523 start offset/unbound
524 */
525
526/* printf("%2s %2d %5d %s %6u %5d %d %5d\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700527 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
528 i,
529 pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
530 pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_MAP ? "map " :
531 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_ARRAY ? "array" :
532 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
533 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_NONE ? "none " : "?????"))),
534 pNesting->pMapsAndArrays[i].u.ma.uStartOffset,
535 pNesting->pMapsAndArrays[i].u.ma.uCountTotal,
536 0, // TODO: fix this
537 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset
538 );
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700539*/
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700540 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700541 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700542}
543
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700544
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800547 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
548
549 The following four functions are pretty wrappers for invocation of
550 the string allocator supplied by the caller.
551
Laurence Lundbladeee851742020-01-08 08:37:05 -0800552 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800553
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554static inline void
555StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556{
557 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
558}
559
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560// StringAllocator_Reallocate called with pMem NULL is
561// equal to StringAllocator_Allocate()
562static inline UsefulBuf
563StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
564 void *pMem,
565 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800566{
567 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
568}
569
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570static inline UsefulBuf
571StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800572{
573 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
574}
575
Laurence Lundbladeee851742020-01-08 08:37:05 -0800576static inline void
577StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578{
579 if(pMe->pfAllocator) {
580 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
581 }
582}
583
584
585
Laurence Lundbladeee851742020-01-08 08:37:05 -0800586/*===========================================================================
587 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800589 See qcbor/qcbor_decode.h for definition of the object
590 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592/*
593 Public function, see header file
594 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595void QCBORDecode_Init(QCBORDecodeContext *me,
596 UsefulBufC EncodedCBOR,
597 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598{
599 memset(me, 0, sizeof(QCBORDecodeContext));
600 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 // Don't bother with error check on decode mode. If a bad value is
602 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700603 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700604 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700605 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700606 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700607 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700608}
609
610
611/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700612 Public function, see header file
613 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
615 QCBORStringAllocate pfAllocateFunction,
616 void *pAllocateContext,
617 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700618{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800619 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
620 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
621 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622}
623
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800624
625/*
626 Public function, see header file
627 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800628void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
629 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700630{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700631 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700632}
633
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700634
635/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800636 This decodes the fundamental part of a CBOR data item, the type and
637 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800640
Laurence Lundbladeee851742020-01-08 08:37:05 -0800641 This does the network->host byte order conversion. The conversion
642 here also results in the conversion for floats in addition to that
643 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800644
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700645 This returns:
646 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800647
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800649 tags and floats and length for strings and arrays
650
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800651 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800652 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800653
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800654 The int type is preferred to uint8_t for some variables as this
655 avoids integer promotions, can reduce code size and makes
656 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800658inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
659 int *pnMajorType,
660 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800661 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700663 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800664
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800669 const int nTmpMajorType = nInitialByte >> 5;
670 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800672 // Where the number or argument accumulates
673 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800674
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700676 // Need to get 1,2,4 or 8 additional argument bytes. Map
677 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800678 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800679
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800680 // Loop getting all the bytes in the argument
681 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800683 // This shift and add gives the endian conversion
684 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
685 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800686 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800687 // The reserved and thus-far unused additional info values
688 nReturn = QCBOR_ERR_UNSUPPORTED;
689 goto Done;
690 } else {
691 // Less than 24, additional info is argument or 31, an indefinite length
692 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800695
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696 if(UsefulInputBuf_GetError(pUInBuf)) {
697 nReturn = QCBOR_ERR_HIT_END;
698 goto Done;
699 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 // All successful if we got here.
702 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800703 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800704 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800705 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800706
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700707Done:
708 return nReturn;
709}
710
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800713 CBOR doesn't explicitly specify two's compliment for integers but all
714 CPUs use it these days and the test vectors in the RFC are so. All
715 integers in the CBOR structure are positive and the major type
716 indicates positive or negative. CBOR can express positive integers
717 up to 2^x - 1 where x is the number of bits and negative integers
718 down to 2^x. Note that negative numbers can be one more away from
719 zero than positive. Stdint, as far as I can tell, uses two's
720 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800723 used carefully here, and in particular why it isn't used in the interface.
724 Also see
725 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
726
727 Int is used for values that need less than 16-bits and would be subject
728 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800730inline static QCBORError
731DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700733 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800734
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
736 if (uNumber <= INT64_MAX) {
737 pDecodedItem->val.int64 = (int64_t)uNumber;
738 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800739
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740 } else {
741 pDecodedItem->val.uint64 = uNumber;
742 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744 }
745 } else {
746 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747 // CBOR's representation of negative numbers lines up with the
748 // two-compliment representation. A negative integer has one
749 // more in range than a positive integer. INT64_MIN is
750 // equal to (-INT64_MAX) - 1.
751 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700752 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700754 } else {
755 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000756 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757 nReturn = QCBOR_ERR_INT_OVERFLOW;
758 }
759 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800760
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700761 return nReturn;
762}
763
764// Make sure #define value line up as DecodeSimple counts on this.
765#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
766#error QCBOR_TYPE_FALSE macro value wrong
767#endif
768
769#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
770#error QCBOR_TYPE_TRUE macro value wrong
771#endif
772
773#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
774#error QCBOR_TYPE_NULL macro value wrong
775#endif
776
777#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
778#error QCBOR_TYPE_UNDEF macro value wrong
779#endif
780
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700781#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
782#error QCBOR_TYPE_BREAK macro value wrong
783#endif
784
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
786#error QCBOR_TYPE_DOUBLE macro value wrong
787#endif
788
789#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
790#error QCBOR_TYPE_FLOAT macro value wrong
791#endif
792
793/*
794 Decode true, false, floats, break...
795 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800796inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800797DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700799 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800802 // above make sure uAdditionalInfo values line up with uDataType values.
803 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
804 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800806 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800807 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
808 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800809
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700810 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700811 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
812 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700813 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700814 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700815 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
816 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700817 break;
818 case DOUBLE_PREC_FLOAT:
819 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700820 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700821 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 case CBOR_SIMPLEV_FALSE: // 20
824 case CBOR_SIMPLEV_TRUE: // 21
825 case CBOR_SIMPLEV_NULL: // 22
826 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700827 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800829
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 case CBOR_SIMPLEV_ONEBYTE: // 24
831 if(uNumber <= CBOR_SIMPLE_BREAK) {
832 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700833 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834 goto Done;
835 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800836 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 default: // 0-19
840 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800841 /*
842 DecodeTypeAndNumber will make uNumber equal to
843 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
844 safe because the 2, 4 and 8 byte lengths of uNumber are in
845 the double/float cases above
846 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 pDecodedItem->val.uSimple = (uint8_t)uNumber;
848 break;
849 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800850
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700851Done:
852 return nReturn;
853}
854
855
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700856/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530857 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800859inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
860 int nMajorType,
861 uint64_t uStrLen,
862 UsefulInputBuf *pUInBuf,
863 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700865 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800866
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800867 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
868 // This check makes the casts to size_t below safe.
869
870 // 4 bytes less than the largest sizeof() so this can be tested by
871 // putting a SIZE_MAX length in the CBOR test input (no one will
872 // care the limit on strings is 4 bytes shorter).
873 if(uStrLen > SIZE_MAX-4) {
874 nReturn = QCBOR_ERR_STRING_TOO_LONG;
875 goto Done;
876 }
877
878 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 if(UsefulBuf_IsNULLC(Bytes)) {
880 // Failed to get the bytes for this string item
881 nReturn = QCBOR_ERR_HIT_END;
882 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700883 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800885 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530886 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530888 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700889 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530890 goto Done;
891 }
892 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800893 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530894 } else {
895 // Normal case with no string allocator
896 pDecodedItem->val.string = Bytes;
897 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800898 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800899 // Cast because ternary operator causes promotion to integer
900 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
901 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800902
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530903Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904 return nReturn;
905}
906
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700909
910
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700911
912
Laurence Lundbladeee851742020-01-08 08:37:05 -0800913// Make sure the constants align as this is assumed by
914// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
916#error QCBOR_TYPE_ARRAY value not lined up with major type
917#endif
918#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
919#error QCBOR_TYPE_MAP value not lined up with major type
920#endif
921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923 This gets a single data item and decodes it including preceding
924 optional tagging. This does not deal with arrays and maps and nesting
925 except to decode the data item introducing them. Arrays and maps are
926 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladeee851742020-01-08 08:37:05 -0800928 Errors detected here include: an array that is too long to decode,
929 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
932 QCBORItem *pDecodedItem,
933 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700935 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladeee851742020-01-08 08:37:05 -0800937 /*
938 Get the major type and the number. Number could be length of more
939 bytes or the value depending on the major type nAdditionalInfo is
940 an encoding of the length of the uNumber and is needed to decode
941 floats and doubles
942 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800943 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700944 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800945 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700947 memset(pDecodedItem, 0, sizeof(QCBORItem));
948
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800949 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 // Error out here if we got into trouble on the type and number. The
952 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700953 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700955 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladeee851742020-01-08 08:37:05 -0800957 // At this point the major type and the value are valid. We've got
958 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
961 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800962 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700963 nReturn = QCBOR_ERR_BAD_INT;
964 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700966 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
970 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800971 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
972 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
973 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
974 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530975 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800977 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 }
979 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
982 case CBOR_MAJOR_TYPE_MAP: // Major type 5
983 // Record the number of items in the array or map
984 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
985 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
986 goto Done;
987 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700989 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800991 // type conversion OK because of check above
992 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800994 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800995 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
996 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700997 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001001 nReturn = QCBOR_ERR_BAD_INT;
1002 } else {
1003 pDecodedItem->val.uTagV = uNumber;
1004 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
1005 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001006 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001007
Laurence Lundbladeee851742020-01-08 08:37:05 -08001008 case CBOR_MAJOR_TYPE_SIMPLE:
1009 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001010 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundbladeee851742020-01-08 08:37:05 -08001013 default:
1014 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015 nReturn = QCBOR_ERR_UNSUPPORTED;
1016 break;
1017 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019Done:
1020 return nReturn;
1021}
1022
1023
1024
1025/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001026 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001027 individual chunk items together into one QCBORItem using the string
1028 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001029
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301030 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001032static inline QCBORError
1033GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001034{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001035 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001036
1037 // Get pointer to string allocator. First use is to pass it to
1038 // GetNext_Item() when option is set to allocate for *every* string.
1039 // Second use here is to allocate space to coallese indefinite
1040 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001041 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1042 &(me->StringAllocator) :
1043 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001045 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001046 nReturn = GetNext_Item(&(me->InBuf),
1047 pDecodedItem,
1048 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049 if(nReturn) {
1050 goto Done;
1051 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301054 // code in this function from here down can be eliminated. Run tests, except
1055 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001057 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001058 const uint8_t uStringType = pDecodedItem->uDataType;
1059 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 goto Done; // no need to do any work here on non-string types
1061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001063 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301064 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001065 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301068 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001069 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1071 goto Done;
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001074 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001075 UsefulBufC FullString = NULLUsefulBufC;
1076
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001077 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001078 // Get item for next chunk
1079 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001080 // NULL string allocator passed here. Do not need to allocate
1081 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001082 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001084 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001088 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001089 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001090 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301091 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001092 break;
1093 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001094
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001095 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301096 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001097 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001098 if(StringChunkItem.uDataType != uStringType ||
1099 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001100 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101 break;
1102 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001103
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301104 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001105 // The first time throurgh FullString.ptr is NULL and this is
1106 // equivalent to StringAllocator_Allocate()
1107 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1108 UNCONST_POINTER(FullString.ptr),
1109 FullString.len + StringChunkItem.val.string.len);
1110
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301112 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001113 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001114 break;
1115 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001117 // Copy new string chunk at the end of string so far.
1118 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001121 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1122 // Getting the item failed, clean up the allocated memory
1123 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001125
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001126Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001127 return nReturn;
1128}
1129
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001130
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001131static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1132 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133 return uTagVal;
1134 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001135 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001136 return me->auMappedTags[x];
1137 }
1138}
1139
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001140/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001141 Gets all optional tag data items preceding a data item that is not an
1142 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001143 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001144static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001145GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001146{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001147 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001149 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1150 CBOR_TAG_INVALID16,
1151 CBOR_TAG_INVALID16,
1152 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001153
Laurence Lundblade59289e52019-12-30 13:44:37 -08001154 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001155 for(;;) {
1156 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001157 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001158 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001160
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001161 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1162 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001163 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001164 break;
1165 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001166
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001167 // Is there room for the tag in the tags list?
1168 size_t uTagIndex;
1169 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001170 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001171 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001172 }
1173 }
1174 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001175 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001177
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001178 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001179 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001180 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001181 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001182 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001183 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001184 break;
1185 }
1186 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001187 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188 break;
1189 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001190 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001191 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1192 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001193 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1194 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001195 }
1196
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001197 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001198 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001199 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001200
1201 } else {
1202 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001203 }
1204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001205
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206Done:
1207 return nReturn;
1208}
1209
1210
1211/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001212 This layer takes care of map entries. It combines the label and data
1213 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001214 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001215static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001216GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001217{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001218 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001220 if(nReturn)
1221 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001222
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001223 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001224 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001225 goto Done;
1226 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001227
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001228 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1229 // In a map and caller wants maps decoded, not treated as arrays
1230
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001231 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001232 // If in a map and the right decoding mode, get the label
1233
Laurence Lundbladeee851742020-01-08 08:37:05 -08001234 // Save label in pDecodedItem and get the next which will
1235 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001236 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001237 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001238 if(nReturn)
1239 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001240
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301241 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001242
1243 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1244 // strings are always good labels
1245 pDecodedItem->label.string = LabelItem.val.string;
1246 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1247 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001248 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001249 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1250 goto Done;
1251 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1252 pDecodedItem->label.int64 = LabelItem.val.int64;
1253 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1254 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1255 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1256 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1257 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1258 pDecodedItem->label.string = LabelItem.val.string;
1259 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1260 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1261 } else {
1262 // label is not an int or a string. It is an arrray
1263 // or a float or such and this implementation doesn't handle that.
1264 // Also, tags on labels are ignored.
1265 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1266 goto Done;
1267 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001268 }
1269 } else {
1270 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001271 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1272 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1273 goto Done;
1274 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001275 // Decoding a map as an array
1276 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001277 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1278 // Cast is needed because of integer promotion
1279 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001280 }
1281 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001282
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001283Done:
1284 return nReturn;
1285}
1286
1287
Laurence Lundblade02625d42020-06-25 14:41:41 -07001288/*
1289 See if next item is a CBOR break. If it is, it is consumed,
1290 if not it is not consumed.
1291*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001292static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001293NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1294{
1295 *pbNextIsBreak = false;
1296 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001297 QCBORItem Peek;
1298 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1299 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1300 if(uReturn != QCBOR_SUCCESS) {
1301 return uReturn;
1302 }
1303 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001304 // It is not a break, rewind so it can be processed normally.
1305 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001306 } else {
1307 *pbNextIsBreak = true;
1308 }
1309 }
1310
1311 return QCBOR_SUCCESS;
1312}
1313
1314
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001315/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001316 An item was just consumed, now figure out if it was the
1317 end of an array or map that can be closed out. That
1318 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001319*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001320static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001321{
1322 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001323
Laurence Lundblade642282a2020-06-23 12:00:33 -07001324 /* This loops ascending nesting levels as long as there is ascending to do */
1325 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1326
1327 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001328 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001329 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1330 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001331 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001332 break;
1333 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001334 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001335
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001336 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001337 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001338 bool bIsBreak = false;
1339 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1340 if(uReturn != QCBOR_SUCCESS) {
1341 goto Done;
1342 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001343
1344 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001345 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001346 break;
1347 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001348
1349 if(DecodeNesting_IsBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001350 /*
1351 Break occurred inside a bstr-wrapped CBOR or
1352 in the top level sequence. This is always an
1353 error because neither are an indefinte length
1354 map/array.
1355 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001356 uReturn = QCBOR_ERR_BAD_BREAK;
1357 goto Done;
1358 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001359 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001360 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001361
Laurence Lundblade02625d42020-06-25 14:41:41 -07001362 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001363
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001364 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001365 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001366 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001367 if(bMarkEnd) {
1368 // Used for definite and indefinite to signal end
1369 DecodeNesting_ZeroDefiniteLengthCount(&(pMe->nesting));
1370
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001371 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001372 break;
1373 }
1374
1375 /* Finally, actually ascend one level. */
1376 DecodeNesting_Ascend(&(pMe->nesting));
1377 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001378
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001379 uReturn = QCBOR_SUCCESS;
1380
1381Done:
1382 return uReturn;
1383}
1384
1385
1386/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001387 This the travesal going descending into and asecnding out of maps,
1388 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1389 indefinte length maps and arrays by looking at the item count or
1390 finding CBOR breaks. It detects the ends of the top-level sequence
1391 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001392 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001393static QCBORError
1394QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001395{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001397 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001398
Laurence Lundblade642282a2020-06-23 12:00:33 -07001399 /*
1400 If out of bytes to consume, it is either the end of the top-level
1401 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001402
Laurence Lundblade642282a2020-06-23 12:00:33 -07001403 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1404 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1405 CBOR is exited, the length is set back to the top-level's length
1406 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001407
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1409 when at the top level to allow other code below to process various
1410 errors when out of bytes to decode and not at the top level. Note
1411 that QCBORDecode_Finish() still needs to be called to be sure all
1412 nesting levels were closed out.
1413 */
1414 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1415 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001416 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001417 goto Done;
1418 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001419
Laurence Lundblade642282a2020-06-23 12:00:33 -07001420 /*
1421 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001422 array. The check for the end of an indefinite length array is
1423 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001424 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001425 if(DecodeNesting_IsAtEndOfBoundedFarf(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001426 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001427 goto Done;
1428 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001429
Laurence Lundblade642282a2020-06-23 12:00:33 -07001430 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001431 uReturn = GetNext_MapEntry(me, pDecodedItem);
1432 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001433 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001434 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301435
Laurence Lundblade642282a2020-06-23 12:00:33 -07001436 /*
1437 Breaks ending arrays/maps are always processed at the end of this
1438 function. They should never show up here.
1439 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301440 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001441 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301442 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001444
Laurence Lundblade642282a2020-06-23 12:00:33 -07001445 /*
1446 Record the nesting level for this data item before processing any
1447 of decrementing and descending.
1448 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001449 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001450
Laurence Lundblade642282a2020-06-23 12:00:33 -07001451
1452 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001453 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001454 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001455 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457 Empty maps and arrays descended into, but then ascended out
1458 of in the next chunk of code.
1459
1460 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001461 encloses them so a decrement needs to be done for them too, but
1462 that is done only when all the items in them have been
1463 processed, not when they are opened with the exception of an
1464 empty map or array.
1465 */
1466 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1467 pDecodedItem->uDataType,
1468 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001469 if(uReturn != QCBOR_SUCCESS) {
1470 goto Done;
1471 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001472 }
1473
Laurence Lundblade02625d42020-06-25 14:41:41 -07001474 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1475 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1476 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477 /*
1478 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001479 - A non-aggregate like an integer or string
1480 - An empty definite length map or array
1481 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001482
1483 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001484 definite length map/array and break detection for an indefinite
1485 length map/array. If the end of the map/array was reached, then
1486 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001487 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001488 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001489 if(uReturn) {
1490 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001491 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301492 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001493
Laurence Lundblade02625d42020-06-25 14:41:41 -07001494 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001496 Tell the caller what level is next. This tells them what
1497 maps/arrays were closed out and makes it possible for them to
1498 reconstruct the tree with just the information returned in
1499 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001500 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001501 if(DecodeNesting_IsAtEndOfBoundedFarf(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001502 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001503 pDecodedItem->uNextNestLevel = 0;
1504 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001505 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001506 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001507
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001508Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001509 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001510 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001511 memset(pDecodedItem, 0, sizeof(QCBORItem));
1512 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001513 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001514}
1515
1516
Laurence Lundblade59289e52019-12-30 13:44:37 -08001517/*
1518 Mostly just assign the right data type for the date string.
1519 */
1520inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1521{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001522 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1523 return QCBOR_ERR_BAD_OPT_TAG;
1524 }
1525
1526 const UsefulBufC Temp = pDecodedItem->val.string;
1527 pDecodedItem->val.dateString = Temp;
1528 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1529 return QCBOR_SUCCESS;
1530}
1531
1532
1533/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001534 The epoch formatted date. Turns lots of different forms of encoding
1535 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001536 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001537static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001538{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001539 QCBORError nReturn = QCBOR_SUCCESS;
1540
1541 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1542
1543 switch (pDecodedItem->uDataType) {
1544
1545 case QCBOR_TYPE_INT64:
1546 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1547 break;
1548
1549 case QCBOR_TYPE_UINT64:
1550 if(pDecodedItem->val.uint64 > INT64_MAX) {
1551 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1552 goto Done;
1553 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001554 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001555 break;
1556
1557 case QCBOR_TYPE_DOUBLE:
1558 {
1559 // This comparison needs to be done as a float before
1560 // conversion to an int64_t to be able to detect doubles
1561 // that are too large to fit into an int64_t. A double
1562 // has 52 bits of preceision. An int64_t has 63. Casting
1563 // INT64_MAX to a double actually causes a round up which
1564 // is bad and wrong for the comparison because it will
1565 // allow conversion of doubles that can't fit into a
1566 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1567 // the cutoff point as if that rounds up in conversion to
1568 // double it will still be less than INT64_MAX. 0x7ff is
1569 // picked because it has 11 bits set.
1570 //
1571 // INT64_MAX seconds is on the order of 10 billion years,
1572 // and the earth is less than 5 billion years old, so for
1573 // most uses this conversion error won't occur even though
1574 // doubles can go much larger.
1575 //
1576 // Without the 0x7ff there is a ~30 minute range of time
1577 // values 10 billion years in the past and in the future
1578 // where this this code would go wrong.
1579 const double d = pDecodedItem->val.dfnum;
1580 if(d > (double)(INT64_MAX - 0x7ff)) {
1581 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1582 goto Done;
1583 }
1584 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1585 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1586 }
1587 break;
1588
1589 default:
1590 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1591 goto Done;
1592 }
1593 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1594
1595Done:
1596 return nReturn;
1597}
1598
1599
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001600/*
1601 Mostly just assign the right data type for the bignum.
1602 */
1603inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1604{
1605 // Stack Use: UsefulBuf 1 -- 16
1606 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1607 return QCBOR_ERR_BAD_OPT_TAG;
1608 }
1609 const UsefulBufC Temp = pDecodedItem->val.string;
1610 pDecodedItem->val.bigNum = Temp;
1611 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1612 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1613 : QCBOR_TYPE_NEGBIGNUM);
1614 return QCBOR_SUCCESS;
1615}
1616
1617
Laurence Lundblade59289e52019-12-30 13:44:37 -08001618#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1619/*
1620 Decode decimal fractions and big floats.
1621
1622 When called pDecodedItem must be the array that is tagged as a big
1623 float or decimal fraction, the array that has the two members, the
1624 exponent and mantissa.
1625
1626 This will fetch and decode the exponent and mantissa and put the
1627 result back into pDecodedItem.
1628 */
1629inline static QCBORError
1630QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1631{
1632 QCBORError nReturn;
1633
1634 // --- Make sure it is an array; track nesting level of members ---
1635 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1636 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1637 goto Done;
1638 }
1639
1640 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001641 // definite length arrays, but not for indefnite. Instead remember
1642 // the nesting level the two integers must be at, which is one
1643 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001644 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1645
1646 // --- Is it a decimal fraction or a bigfloat? ---
1647 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1648 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1649
1650 // --- Get the exponent ---
1651 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001652 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001653 if(nReturn != QCBOR_SUCCESS) {
1654 goto Done;
1655 }
1656 if(exponentItem.uNestingLevel != nNestLevel) {
1657 // Array is empty or a map/array encountered when expecting an int
1658 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1659 goto Done;
1660 }
1661 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1662 // Data arriving as an unsigned int < INT64_MAX has been converted
1663 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1664 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1665 // will be too large for this to handle and thus an error that will
1666 // get handled in the next else.
1667 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1668 } else {
1669 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1670 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1671 goto Done;
1672 }
1673
1674 // --- Get the mantissa ---
1675 QCBORItem mantissaItem;
1676 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1677 if(nReturn != QCBOR_SUCCESS) {
1678 goto Done;
1679 }
1680 if(mantissaItem.uNestingLevel != nNestLevel) {
1681 // Mantissa missing or map/array encountered when expecting number
1682 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1683 goto Done;
1684 }
1685 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1686 // Data arriving as an unsigned int < INT64_MAX has been converted
1687 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1688 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1689 // will be too large for this to handle and thus an error that
1690 // will get handled in an else below.
1691 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1692 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1693 // Got a good big num mantissa
1694 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1695 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001696 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1697 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1698 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001699 } else {
1700 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1701 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1702 goto Done;
1703 }
1704
1705 // --- Check that array only has the two numbers ---
1706 if(mantissaItem.uNextNestLevel == nNestLevel) {
1707 // Extra items in the decimal fraction / big num
1708 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1709 goto Done;
1710 }
1711
1712Done:
1713
1714 return nReturn;
1715}
1716#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1717
1718
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001719
1720/*
1721 */
1722inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1723{
1724 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1725 return QCBOR_ERR_BAD_OPT_TAG;
1726 }
1727 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1728 return QCBOR_SUCCESS;
1729}
1730
1731
1732inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1733{
1734 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1735 return QCBOR_ERR_BAD_OPT_TAG;
1736 }
1737 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1738 return QCBOR_SUCCESS;
1739}
1740
1741
1742inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1743{
1744 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1745 return QCBOR_ERR_BAD_OPT_TAG;
1746 }
1747 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1748 return QCBOR_SUCCESS;
1749}
1750
1751
1752inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1753{
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1755 return QCBOR_ERR_BAD_OPT_TAG;
1756 }
1757 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1758 return QCBOR_SUCCESS;
1759}
1760
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001761inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1762{
1763 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1764 return QCBOR_ERR_BAD_OPT_TAG;
1765 }
1766 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1767 return QCBOR_SUCCESS;
1768}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001769
1770inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1771{
1772 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1773 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1774 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1775 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1776 } else {
1777 return QCBOR_ERR_BAD_OPT_TAG;
1778 }
1779 return QCBOR_SUCCESS;
1780}
1781
1782
1783/*
1784 */
1785inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1786{
1787 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1788 return QCBOR_ERR_BAD_OPT_TAG;
1789 }
1790 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1791 return QCBOR_SUCCESS;
1792}
1793
1794
Laurence Lundblade59289e52019-12-30 13:44:37 -08001795/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001796 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001797 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001798QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800{
1801 QCBORError nReturn;
1802
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001803 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001804 if(nReturn != QCBOR_SUCCESS) {
1805 goto Done;
1806 }
1807
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001808 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1809 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001810
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001811 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812 nReturn = DecodeDateString(pDecodedItem);
1813 break;
1814
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001815 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001816 nReturn = DecodeDateEpoch(pDecodedItem);
1817 break;
1818
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001819 case CBOR_TAG_POS_BIGNUM:
1820 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001821 nReturn = DecodeBigNum(pDecodedItem);
1822 break;
1823
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001824 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1825 case CBOR_TAG_DECIMAL_FRACTION:
1826 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001827 // For aggregate tagged types, what goes into pTags is only collected
1828 // from the surrounding data item, not the contents, so pTags is not
1829 // passed on here.
1830
1831 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1832 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001833 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001834
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001835 case CBOR_TAG_CBOR:
1836 nReturn = DecodeWrappedCBOR(pDecodedItem);
1837 break;
1838
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001839 case CBOR_TAG_URI:
1840 nReturn = DecodeURI(pDecodedItem);
1841 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001842
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001843 case CBOR_TAG_B64URL:
1844 nReturn = DecodeB64URL(pDecodedItem);
1845 break;
1846
1847 case CBOR_TAG_B64:
1848 nReturn = DecodeB64(pDecodedItem);
1849 break;
1850
1851 case CBOR_TAG_MIME:
1852 case CBOR_TAG_BINARY_MIME:
1853 nReturn = DecodeMIME(pDecodedItem);
1854 break;
1855
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001856 case CBOR_TAG_REGEX:
1857 nReturn = DecodeRegex(pDecodedItem);
1858 break;
1859
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001860 case CBOR_TAG_BIN_UUID:
1861 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001862 break;
1863
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001864 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001865 // The end of the tag list or no tags
1866 // Successful exit from the loop.
1867 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001868
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001869 default:
1870 // A tag that is not understood
1871 // A successful exit from the loop
1872 goto Done;
1873
1874 }
1875 if(nReturn != QCBOR_SUCCESS) {
1876 goto Done;
1877 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001878 }
1879
1880Done:
1881 if(nReturn != QCBOR_SUCCESS) {
1882 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1883 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1884 }
1885 return nReturn;
1886}
1887
1888
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001889QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1890{
1891 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1892
1893 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1894
1895 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1896
1897 return uErr;
1898}
1899
1900
Laurence Lundblade59289e52019-12-30 13:44:37 -08001901/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001902 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001903 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001904QCBORError
1905QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1906 QCBORItem *pDecodedItem,
1907 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001908{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001909 QCBORError nReturn;
1910
1911 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1912 if(nReturn != QCBOR_SUCCESS) {
1913 return nReturn;
1914 }
1915
1916 if(pTags != NULL) {
1917 pTags->uNumUsed = 0;
1918 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001919 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001920 break;
1921 }
1922 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1923 return QCBOR_ERR_TOO_MANY_TAGS;
1924 }
1925 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1926 pTags->uNumUsed++;
1927 }
1928 }
1929
1930 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001931}
1932
1933
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001934/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301935 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301936 next one down. If a layer has no work to do for a particular item
1937 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001938
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1940 tagged data items, turning them into the local C representation.
1941 For the most simple it is just associating a QCBOR_TYPE with the data. For
1942 the complex ones that an aggregate of data items, there is some further
1943 decoding and a little bit of recursion.
1944
1945 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301946 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301947 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001948 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301950 - GetNext_MapEntry -- This handles the combining of two
1951 items, the label and the data, that make up a map entry.
1952 It only does work on maps. It combines the label and data
1953 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001954
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1956 tags into bit flags associated with the data item. No actual decoding
1957 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001958
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301960 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301961 string allocater to create contiguous space for the item. It
1962 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001963
Laurence Lundblade59289e52019-12-30 13:44:37 -08001964 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1965 atomic data item has a "major type", an integer "argument" and optionally
1966 some content. For text and byte strings, the content is the bytes
1967 that make up the string. These are the smallest data items that are
1968 considered to be well-formed. The content may also be other data items in
1969 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001970
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001971 Roughly this takes 300 bytes of stack for vars. Need to
1972 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001973
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301974 */
1975
1976
1977/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001978 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001979 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001980int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001981 const QCBORItem *pItem,
1982 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001983{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001984 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001985 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001986 break;
1987 }
1988 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1989 return 1;
1990 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001991 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001992
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001993 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001994}
1995
1996
1997/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001998 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001999 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002000QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002001{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002002 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002003
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002004 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002005 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002006 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
2007 goto Done;
2008 }
2009
2010 // Error out if not all the bytes are consumed
2011 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
2012 nReturn = QCBOR_ERR_EXTRA_BYTES;
2013 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002014
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002015Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302016 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002017 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002018 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002019
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002020 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002021}
2022
2023
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002024/*
2025Public function, see header qcbor/qcbor_decode.h file
2026*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002027uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2028 const QCBORItem *pItem,
2029 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002030{
2031 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2032 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002033 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002034 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002035 }
2036}
2037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002038
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002039/*
2040
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002041Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002042
Laurence Lundbladeee851742020-01-08 08:37:05 -08002043 - Hit end of input before it was expected while decoding type and
2044 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002046 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002047
Laurence Lundbladeee851742020-01-08 08:37:05 -08002048 - Hit end of input while decoding a text or byte string
2049 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002050
Laurence Lundbladeee851742020-01-08 08:37:05 -08002051 - Encountered conflicting tags -- e.g., an item is tagged both a date
2052 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundbladeee851742020-01-08 08:37:05 -08002054 - Encontered an array or mapp that has too many items
2055 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002056
Laurence Lundbladeee851742020-01-08 08:37:05 -08002057 - Encountered array/map nesting that is too deep
2058 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002059
Laurence Lundbladeee851742020-01-08 08:37:05 -08002060 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2061 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002062
Laurence Lundbladeee851742020-01-08 08:37:05 -08002063 - The type of a map label is not a string or int
2064 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002065
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002066 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002067
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002068 */
2069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002070
2071
Laurence Lundbladef6531662018-12-04 10:42:22 +09002072
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002073/* ===========================================================================
2074 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002075
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002076 This implements a simple sting allocator for indefinite length
2077 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2078 implements the function type QCBORStringAllocate and allows easy
2079 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002080
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002081 This particular allocator is built-in for convenience. The caller
2082 can implement their own. All of this following code will get
2083 dead-stripped if QCBORDecode_SetMemPool() is not called.
2084
2085 This is a very primitive memory allocator. It does not track
2086 individual allocations, only a high-water mark. A free or
2087 reallocation must be of the last chunk allocated.
2088
2089 The size of the pool and offset to free memory are packed into the
2090 first 8 bytes of the memory pool so we don't have to keep them in
2091 the decode context. Since the address of the pool may not be
2092 aligned, they have to be packed and unpacked as if they were
2093 serialized data of the wire or such.
2094
2095 The sizes packed in are uint32_t to be the same on all CPU types
2096 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002097 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002098
2099
Laurence Lundbladeee851742020-01-08 08:37:05 -08002100static inline int
2101MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002102{
2103 // Use of UsefulInputBuf is overkill, but it is convenient.
2104 UsefulInputBuf UIB;
2105
Laurence Lundbladeee851742020-01-08 08:37:05 -08002106 // Just assume the size here. It was checked during SetUp so
2107 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002108 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2109 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2110 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2111 return UsefulInputBuf_GetError(&UIB);
2112}
2113
2114
Laurence Lundbladeee851742020-01-08 08:37:05 -08002115static inline int
2116MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002117{
2118 // Use of UsefulOutBuf is overkill, but convenient. The
2119 // length check performed here is useful.
2120 UsefulOutBuf UOB;
2121
2122 UsefulOutBuf_Init(&UOB, Pool);
2123 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2124 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2125 return UsefulOutBuf_GetError(&UOB);
2126}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002127
2128
2129/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002130 Internal function for an allocation, reallocation free and destuct.
2131
2132 Having only one function rather than one each per mode saves space in
2133 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002134
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002135 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2136 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002137static UsefulBuf
2138MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002139{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002140 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002141
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002142 uint32_t uPoolSize;
2143 uint32_t uFreeOffset;
2144
2145 if(uNewSize > UINT32_MAX) {
2146 // This allocator is only good up to 4GB. This check should
2147 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2148 goto Done;
2149 }
2150 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2151
2152 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2153 goto Done;
2154 }
2155
2156 if(uNewSize) {
2157 if(pMem) {
2158 // REALLOCATION MODE
2159 // Calculate pointer to the end of the memory pool. It is
2160 // assumed that pPool + uPoolSize won't wrap around by
2161 // assuming the caller won't pass a pool buffer in that is
2162 // not in legitimate memory space.
2163 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2164
2165 // Check that the pointer for reallocation is in the range of the
2166 // pool. This also makes sure that pointer math further down
2167 // doesn't wrap under or over.
2168 if(pMem >= pPool && pMem < pPoolEnd) {
2169 // Offset to start of chunk for reallocation. This won't
2170 // wrap under because of check that pMem >= pPool. Cast
2171 // is safe because the pool is always less than UINT32_MAX
2172 // because of check in QCBORDecode_SetMemPool().
2173 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2174
2175 // Check to see if the allocation will fit. uPoolSize -
2176 // uMemOffset will not wrap under because of check that
2177 // pMem is in the range of the uPoolSize by check above.
2178 if(uNewSize <= uPoolSize - uMemOffset) {
2179 ReturnValue.ptr = pMem;
2180 ReturnValue.len = uNewSize;
2181
2182 // Addition won't wrap around over because uNewSize was
2183 // checked to be sure it is less than the pool size.
2184 uFreeOffset = uMemOffset + uNewSize32;
2185 }
2186 }
2187 } else {
2188 // ALLOCATION MODE
2189 // uPoolSize - uFreeOffset will not underflow because this
2190 // pool implementation makes sure uFreeOffset is always
2191 // smaller than uPoolSize through this check here and
2192 // reallocation case.
2193 if(uNewSize <= uPoolSize - uFreeOffset) {
2194 ReturnValue.len = uNewSize;
2195 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002196 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002197 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002198 }
2199 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002200 if(pMem) {
2201 // FREE MODE
2202 // Cast is safe because of limit on pool size in
2203 // QCBORDecode_SetMemPool()
2204 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2205 } else {
2206 // DESTRUCT MODE
2207 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002208 }
2209 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002211 UsefulBuf Pool = {pPool, uPoolSize};
2212 MemPool_Pack(Pool, uFreeOffset);
2213
2214Done:
2215 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002216}
2217
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002218
Laurence Lundbladef6531662018-12-04 10:42:22 +09002219/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002220 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002221 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002222QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2223 UsefulBuf Pool,
2224 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002225{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002226 // The pool size and free mem offset are packed into the beginning
2227 // of the pool memory. This compile time check make sure the
2228 // constant in the header is correct. This check should optimize
2229 // down to nothing.
2230 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002231 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002234 // The pool size and free offset packed in to the beginning of pool
2235 // memory are only 32-bits. This check will optimize out on 32-bit
2236 // machines.
2237 if(Pool.len > UINT32_MAX) {
2238 return QCBOR_ERR_BUFFER_TOO_LARGE;
2239 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002240
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002241 // This checks that the pool buffer given is big enough.
2242 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2243 return QCBOR_ERR_BUFFER_TOO_SMALL;
2244 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002246 pMe->StringAllocator.pfAllocator = MemPool_Function;
2247 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2248 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002249
Laurence Lundblade30816f22018-11-10 13:40:22 +07002250 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002251}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002252
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002253
2254
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002255
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002256
2257
2258/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002259 Consume an entire map or array (and do next to
2260 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002261 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002262static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002263ConsumeItem(QCBORDecodeContext *pMe,
2264 const QCBORItem *pItemToConsume,
2265 uint_fast8_t *puNextNestLevel)
2266{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002268 QCBORItem Item;
2269
Laurence Lundblade02625d42020-06-25 14:41:41 -07002270 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002271
Laurence Lundblade02625d42020-06-25 14:41:41 -07002272 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002273 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002274
Laurence Lundblade1341c592020-04-11 14:19:05 -07002275 /* This works for definite and indefinite length
2276 * maps and arrays by using the nesting level
2277 */
2278 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002279 uReturn = QCBORDecode_GetNext(pMe, &Item);
2280 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281 goto Done;
2282 }
2283 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002284
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285 if(puNextNestLevel != NULL) {
2286 *puNextNestLevel = Item.uNextNestLevel;
2287 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002288 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002289
Laurence Lundblade1341c592020-04-11 14:19:05 -07002290 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002291 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002292 if(puNextNestLevel != NULL) {
2293 /* Just pass the nesting level through */
2294 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2295 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002296 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002297 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002298
2299Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002300 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301}
2302
2303
Laurence Lundblade1341c592020-04-11 14:19:05 -07002304/* Return true if the labels in Item1 and Item2 are the same.
2305 Works only for integer and string labels. Returns false
2306 for any other type. */
2307static inline bool
2308MatchLabel(QCBORItem Item1, QCBORItem Item2)
2309{
2310 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2311 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2312 return true;
2313 }
2314 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002315 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002316 return true;
2317 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002318 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002319 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2320 return true;
2321 }
2322 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2323 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2324 return true;
2325 }
2326 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002327
Laurence Lundblade1341c592020-04-11 14:19:05 -07002328 /* Other label types are never matched */
2329 return false;
2330}
2331
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002332
2333/*
2334 Returns true if Item1 and Item2 are the same type
2335 or if either are of QCBOR_TYPE_ANY.
2336 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002337static inline bool
2338MatchType(QCBORItem Item1, QCBORItem Item2)
2339{
2340 if(Item1.uDataType == Item2.uDataType) {
2341 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002342 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002343 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002344 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002345 return true;
2346 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002347 return false;
2348}
2349
2350
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002351/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002352 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002353
2354 @param[in] pMe The decode context to search.
2355 @param[in,out] pItemArray The items to search for and the items found.
2356 @param[in] pCBContext Context for the not-found item call back
2357 @param[in] pfCallback Function to call on items not matched in pItemArray
2358
2359 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2360
2361 @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.
2362
2363 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2364
2365 @retval Also errors returned by QCBORDecode_GetNext().
2366
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002367 On input pItemArray contains a list of labels and data types
2368 of items to be found.
2369
2370 On output the fully retrieved items are filled in with
2371 values and such. The label was matched, so it never changes.
2372
2373 If an item was not found, its data type is set to none.
2374
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002376static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002377MapSearch(QCBORDecodeContext *pMe,
2378 QCBORItem *pItemArray,
2379 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002380 void *pCBContext,
2381 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002382{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002383 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002384
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002385 QCBORDecodeNesting SaveNesting;
2386 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002387
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002388 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002389 UsefulInputBuf_Seek(&(pMe->InBuf),
2390 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002391
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002392 /*
2393 Loop over all the items in the map. They could be
2394 deeply nested and this should handle both definite
2395 and indefinite length maps and arrays, so this
2396 adds some complexity.
2397 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002398 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002399
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002400 uint_fast8_t uNextNestLevel;
2401
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002402 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002403
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002404 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002405 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002406 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002407 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002408
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002409 /* Get the item */
2410 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002411 uReturn = QCBORDecode_GetNext(pMe, &Item);
2412 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002413 /* Got non-well-formed CBOR */
2414 goto Done;
2415 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002416
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002417 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002418 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002419 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002420 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002421 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002422 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002423 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2424 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002425 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002426 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002427 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002428 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002429 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002430 goto Done;
2431 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002432
2433 /* Successful match. Return the item. */
2434 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002435 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002436 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002437 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002438 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002439 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002440 /*
2441 Call the callback on unmatched labels.
2442 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002443 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002444 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002445 */
2446 if(pfCallback) {
2447 uReturn = (*pfCallback)(pCBContext, &Item);
2448 if(uReturn != QCBOR_SUCCESS) {
2449 goto Done;
2450 }
2451 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002452 }
2453 }
2454
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002455 /*
2456 Consume the item whether matched or not. This
2457 does the work of traversing maps and array and
2458 everything in them. In this loop only the
2459 items at the current nesting level are examined
2460 to match the labels.
2461 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002462 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2463 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002464 goto Done;
2465 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002466
2467 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002468
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002469 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002470
2471 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002472 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2473 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002474
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002475 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002476 int i;
2477 QCBORItem *pIterator;
2478 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002479 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002480 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002481 }
2482 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002483
2484Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002485 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002486
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002487 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002488}
2489
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002490
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002491/*
2492Public function, see header qcbor/qcbor_decode.h file
2493*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002494void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2495 int64_t nLabel,
2496 uint8_t uQcborType,
2497 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002498{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002499 if(pMe->uLastError != QCBOR_SUCCESS) {
2500 return;
2501 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002503 QCBORItem OneItemSeach[2];
2504 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2505 OneItemSeach[0].label.int64 = nLabel;
2506 OneItemSeach[0].uDataType = uQcborType;
2507 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002509 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002510 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002511 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002512 }
2513
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002514 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2515 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002516 }
2517
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002518 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002519}
2520
2521
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002522/*
2523Public function, see header qcbor/qcbor_decode.h file
2524*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002525void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2526 const char *szLabel,
2527 uint8_t uQcborType,
2528 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002530 if(pMe->uLastError != QCBOR_SUCCESS) {
2531 return;
2532 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002533
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002534 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002535 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2536 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2537 OneItemSeach[0].uDataType = uQcborType;
2538 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002540 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002541 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002542 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 }
2544
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002545 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002546 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002547 }
2548
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002549 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002550}
2551
2552
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002553/**
2554 @param[in] TagSpec Specification for matching tags.
2555 @param[in] uDataType A QCBOR data type
2556
2557 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2558 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2559
2560 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2561 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002562static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002563{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002564 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2565 /* Must match the tag */
2566 if(uDataType == TagSpec.uTaggedType) {
2567 return QCBOR_SUCCESS;
2568 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002569 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002570 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2571 /* Must check all the possible types for the tag content */
2572 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2574 return QCBOR_SUCCESS;
2575 }
2576 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002577 /* Didn't match any of the tag content types */
2578 /* Check the tag for the either case */
2579 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2580 if(uDataType == TagSpec.uTaggedType) {
2581 return QCBOR_SUCCESS;
2582 }
2583 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002584 }
2585
2586 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002587}
2588
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002589
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002590// Semi-private
2591// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002592void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2593 int64_t nLabel,
2594 TagSpecification TagSpec,
2595 QCBORItem *pItem)
2596{
2597 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2598 if(pMe->uLastError != QCBOR_SUCCESS) {
2599 return;
2600 }
2601
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002602 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002603}
2604
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002605// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002606void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2607 const char *szLabel,
2608 TagSpecification TagSpec,
2609 QCBORItem *pItem)
2610{
2611 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2612 if(pMe->uLastError != QCBOR_SUCCESS) {
2613 return;
2614 }
2615
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002616 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002617}
2618
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002619// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002620void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2621 int64_t nLabel,
2622 TagSpecification TagSpec,
2623 UsefulBufC *pString)
2624{
2625 QCBORItem Item;
2626 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2627 if(pMe->uLastError == QCBOR_SUCCESS) {
2628 *pString = Item.val.string;
2629 }
2630}
2631
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002632// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002633void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2634 const char * szLabel,
2635 TagSpecification TagSpec,
2636 UsefulBufC *pString)
2637{
2638 QCBORItem Item;
2639 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2640 if(pMe->uLastError == QCBOR_SUCCESS) {
2641 *pString = Item.val.string;
2642 }
2643}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002645/*
2646Public function, see header qcbor/qcbor_decode.h file
2647*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002648QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2649{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002650 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002651}
2652
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002653/*
2654Public function, see header qcbor/qcbor_decode.h file
2655*/
2656QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2657 QCBORItem *pItemList,
2658 void *pCallbackCtx,
2659 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002660{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002661 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002662}
2663
2664
Laurence Lundblade34691b92020-05-18 22:25:25 -07002665static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002666{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002667 if(pMe->uLastError != QCBOR_SUCCESS) {
2668 // Already in error state; do nothing.
2669 return;
2670 }
2671
2672 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002673 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002674 if(pMe->uLastError != QCBOR_SUCCESS) {
2675 return;
2676 }
2677
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002678 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002679 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002680
2681 Also need to current map nesting level and start cursor to
2682 be at the right place.
2683
2684 The UsefulInBuf offset could be anywhere, so no assumption is
2685 made about it.
2686
2687 No assumption is made about the pre-order nesting level either.
2688
2689 However the map mode nesting level is assumed to be one above
2690 the map level that is being entered.
2691 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002692 /* Seek to the data item that is the map or array */
2693 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002694 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002695
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002696 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002697}
2698
2699
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002700/*
2701Public function, see header qcbor/qcbor_decode.h file
2702*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002703void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002704{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002705 QCBORItem OneItemSeach[2];
2706 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2707 OneItemSeach[0].label.int64 = nLabel;
2708 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2709 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002710
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002711 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002712 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002713}
2714
2715
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002716/*
2717Public function, see header qcbor/qcbor_decode.h file
2718*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002719void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002720{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002721 QCBORItem OneItemSeach[2];
2722 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2723 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2724 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2725 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002726
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002727 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002728}
2729
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730/*
2731Public function, see header qcbor/qcbor_decode.h file
2732*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002733void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002734{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002735 QCBORItem OneItemSeach[2];
2736 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2737 OneItemSeach[0].label.int64 = nLabel;
2738 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2739 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002740
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002741 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002742}
2743
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002744/*
2745Public function, see header qcbor/qcbor_decode.h file
2746*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002747void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2748{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002749 QCBORItem OneItemSeach[2];
2750 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2751 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2752 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2753 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002755 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002756}
2757
2758
Laurence Lundblade02625d42020-06-25 14:41:41 -07002759// Semi-private function
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002760/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002761void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002762{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002763 if(pMe->uLastError != QCBOR_SUCCESS) {
2764 // Already in error state; do nothing.
2765 return;
2766 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002767
2768 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002769 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002770 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002771 if(pMe->uLastError != QCBOR_SUCCESS) {
2772 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002773 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002774 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002775 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2776 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777 }
2778
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002779 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002780
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002781 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002782 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002783
Laurence Lundblade02625d42020-06-25 14:41:41 -07002784 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002785}
2786
Laurence Lundblade02625d42020-06-25 14:41:41 -07002787
2788/*
2789 This is for exiting a level that is a bounded map, array or bstr
2790 wrapped CBOR. It is the work common to these.
2791
2792 One chunk of work is to set up the pre-order traversal so it is at
2793 the item just after the bounded map, array or bstr that is being
2794 exited. This is somewhat complex.
2795
2796 The other work is to level-up the bounded mode to next higest bounded
2797 mode or the top level if there isn't one.
2798 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002799static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002800ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002801{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002802 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002803
Laurence Lundblade02625d42020-06-25 14:41:41 -07002804 /*
2805 First the pre-order-traversal byte offset is positioned to the
2806 item just after the bounded mode item that was just consumed.
2807 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002808 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2809
Laurence Lundblade02625d42020-06-25 14:41:41 -07002810 /*
2811 Next, set the current nesting level to one above the bounded level
2812 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002813
Laurence Lundblade02625d42020-06-25 14:41:41 -07002814 DecodeNesting_CheckBoundedType() is always called before this and
2815 makes sure pCurrentBounded is valid.
2816 */
2817 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2818
2819 /*
2820 This does the complex work of leveling up the pre-order traversal
2821 when the end of a map or array or another bounded level is
2822 reached. It may do nothing, or ascend all the way to the top
2823 level.
2824 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002825 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002826 if(uErr != QCBOR_SUCCESS) {
2827 goto Done;
2828 }
2829
Laurence Lundblade02625d42020-06-25 14:41:41 -07002830 /*
2831 This makes the next highest bounded level the current bounded
2832 level. If there is no next highest level, then no bounded mode is
2833 in effect.
2834 */
2835 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002836
Laurence Lundblade02625d42020-06-25 14:41:41 -07002837 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002838
2839Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002840 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002841 return uErr;
2842}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002843
Laurence Lundblade02625d42020-06-25 14:41:41 -07002844
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002845// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002846void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002847{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002848 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002849 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002850 return;
2851 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002852
Laurence Lundblade02625d42020-06-25 14:41:41 -07002853 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002854
Laurence Lundblade02625d42020-06-25 14:41:41 -07002855 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002856 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2857 goto Done;
2858 }
2859
Laurence Lundblade02625d42020-06-25 14:41:41 -07002860 /*
2861 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002862 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002863 from previous map search, then do a dummy search.
2864 */
2865 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002866 QCBORItem Dummy;
2867 Dummy.uLabelType = QCBOR_TYPE_NONE;
2868 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2869 if(uErr != QCBOR_SUCCESS) {
2870 goto Done;
2871 }
2872 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002873
Laurence Lundblade02625d42020-06-25 14:41:41 -07002874 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002875
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002876Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002877 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002878}
2879
2880
Laurence Lundblade1341c592020-04-11 14:19:05 -07002881void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002882{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002883 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002884 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2885 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002886}
2887
2888
Laurence Lundblade1341c592020-04-11 14:19:05 -07002889
Laurence Lundblade02625d42020-06-25 14:41:41 -07002890static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe,
2891 const QCBORItem *pItem,
2892 uint8_t uTagRequirement,
2893 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002894{
2895 if(pMe->uLastError != QCBOR_SUCCESS) {
2896 // Already in error state; do nothing.
2897 return pMe->uLastError;
2898 }
2899
2900 QCBORError uError = QCBOR_SUCCESS;
2901
2902 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2903 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2904 goto Done;;
2905 }
2906
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002907 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002908 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2909
2910 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2911 if(uError != QCBOR_SUCCESS) {
2912 goto Done;
2913 }
2914
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002915 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
2916 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002917 so the increment in NestLevelAscender called by ExitBoundedLevel()
2918 will work right. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002919 // TODO: method for this
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002920 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2921 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002922
2923 if(pBstr) {
2924 *pBstr = pItem->val.string;
2925 }
2926
2927 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002928
2929 // Need to move UIB input cursor to the right place
2930
2931 // Really this is a subtraction and an assignment; not much code
2932 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002933 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002934
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002935 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002936
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002937
2938 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2939
2940 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002941
Laurence Lundblade02625d42020-06-25 14:41:41 -07002942 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2943 uPreviousLength,
2944 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002945Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002946 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002947
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002948 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002949}
2950
2951
Laurence Lundblade02625d42020-06-25 14:41:41 -07002952/*
2953 Public function, see header qcbor/qcbor_decode.h file
2954 */
2955void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
2956 uint8_t uTagRequirement,
2957 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002958{
2959 if(pMe->uLastError != QCBOR_SUCCESS) {
2960 // Already in error state; do nothing.
2961 return;
2962 }
2963
2964 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002965 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002966 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2967 if(pMe->uLastError != QCBOR_SUCCESS) {
2968 return;
2969 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002970
Laurence Lundblade02625d42020-06-25 14:41:41 -07002971 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe,
2972 &Item,
2973 uTagRequirement,
2974 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002975}
2976
2977
Laurence Lundblade02625d42020-06-25 14:41:41 -07002978/*
2979 Public function, see header qcbor/qcbor_decode.h file
2980 */
2981void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2982 uint8_t uTagRequirement,
2983 int64_t nLabel,
2984 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002985{
2986 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002987 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002988
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002989 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002990}
2991
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002992
Laurence Lundblade02625d42020-06-25 14:41:41 -07002993/*
2994 Public function, see header qcbor/qcbor_decode.h file
2995 */
2996void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
2997 uint8_t uTagRequirement,
2998 const char *szLabel,
2999 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003000{
3001 QCBORItem Item;
3002 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3003
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003004 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003005}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003006
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003007
Laurence Lundblade02625d42020-06-25 14:41:41 -07003008/*
3009 Public function, see header qcbor/qcbor_decode.h file
3010 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003011void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003012{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003013 if(pMe->uLastError != QCBOR_SUCCESS) {
3014 // Already in error state; do nothing.
3015 return;
3016 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003017
Laurence Lundblade02625d42020-06-25 14:41:41 -07003018 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3019 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3020 return;
3021 }
3022
3023 /*
3024 Reset the length of the UsefulInputBuf to what it was before
3025 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003026 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003027 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3028 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003029
3030
Laurence Lundblade02625d42020-06-25 14:41:41 -07003031 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003032 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003033}
3034
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003035
Laurence Lundbladee6430642020-03-14 21:15:44 -07003036
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003037
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003038
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003039
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003040
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003041
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003042static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3043{
3044 switch(pItem->uDataType) {
3045 case QCBOR_TYPE_TRUE:
3046 *pBool = true;
3047 return QCBOR_SUCCESS;
3048 break;
3049
3050 case QCBOR_TYPE_FALSE:
3051 *pBool = false;
3052 return QCBOR_SUCCESS;
3053 break;
3054
3055 default:
3056 return QCBOR_ERR_UNEXPECTED_TYPE;
3057 break;
3058 }
3059}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003060
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003061/*
3062Public function, see header qcbor/qcbor_decode.h file
3063*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003064void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003065{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003066 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003067 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003068 return;
3069 }
3070
Laurence Lundbladec4537442020-04-14 18:53:22 -07003071 QCBORError nError;
3072 QCBORItem Item;
3073
3074 nError = QCBORDecode_GetNext(pMe, &Item);
3075 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003076 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003077 return;
3078 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003079 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003080}
3081
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082/*
3083Public function, see header qcbor/qcbor_decode.h file
3084*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003085void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003086{
3087 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003088 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003089
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003090 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003091}
3092
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003093/*
3094Public function, see header qcbor/qcbor_decode.h file
3095*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003096void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3097{
3098 QCBORItem Item;
3099 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3100
3101 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3102}
3103
3104
3105
3106void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003107{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003108 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003109 // Already in error state, do nothing
3110 return;
3111 }
3112
3113 QCBORError nError;
3114 QCBORItem Item;
3115
3116 nError = QCBORDecode_GetNext(pMe, &Item);
3117 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003118 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003119 return;
3120 }
3121
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003122 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3123
3124 if(pMe->uLastError == QCBOR_SUCCESS) {
3125 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003126 }
3127}
3128
Laurence Lundbladec4537442020-04-14 18:53:22 -07003129
3130
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003131
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003132static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003133{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003134 *pbIsNegative = false;
3135
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003136 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 -07003137
3138 switch(pItem->uDataType) {
3139 case QCBOR_TYPE_BYTE_STRING:
3140 // TODO: check that there is no tag here?
3141 if(bMustBeTagged) {
3142 return QCBOR_ERR_UNEXPECTED_TYPE;
3143 } else {
3144 *pValue = pItem->val.string;
3145 return QCBOR_SUCCESS;
3146 }
3147 break;
3148
3149 case QCBOR_TYPE_POSBIGNUM:
3150 *pValue = pItem->val.string;
3151 return QCBOR_SUCCESS;
3152 break;
3153
3154 case QCBOR_TYPE_NEGBIGNUM:
3155 *pbIsNegative = true;
3156 *pValue = pItem->val.string;
3157 return QCBOR_SUCCESS;
3158 break;
3159
3160 default:
3161 return QCBOR_ERR_UNEXPECTED_TYPE;
3162 break;
3163 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003164}
3165
3166
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003167/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003168 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3169 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3170 will always be false on the asumption that it is positive, but it can be interpretted as
3171 negative if the the sign is know from other context.
3172 @param[out] pValue The bytes that make up the big num
3173 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3174
3175 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3176 a positive big num or a negative big num.
3177
3178 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003179void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003180{
3181 if(pMe->uLastError != QCBOR_SUCCESS) {
3182 // Already in error state, do nothing
3183 return;
3184 }
3185
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003186 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003187 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3188 if(uError != QCBOR_SUCCESS) {
3189 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003190 return;
3191 }
3192
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003193 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003194}
3195
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003196/*
3197Public function, see header qcbor/qcbor_decode.h file
3198*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003199void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003200{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003201 QCBORItem Item;
3202 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003203
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003204 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003205}
3206
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003207/*
3208Public function, see header qcbor/qcbor_decode.h file
3209*/
3210void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3211{
3212 QCBORItem Item;
3213 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3214
3215 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3216}
3217
3218
3219
3220// Semi private
3221QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3222{
3223 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3224 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3225
3226 QCBORError uReturn;
3227
3228 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3229 *pMessage = pItem->val.string;
3230 if(pbIsNot7Bit != NULL) {
3231 *pbIsNot7Bit = false;
3232 }
3233 uReturn = QCBOR_SUCCESS;
3234 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3235 *pMessage = pItem->val.string;
3236 if(pbIsNot7Bit != NULL) {
3237 *pbIsNot7Bit = true;
3238 }
3239 uReturn = QCBOR_SUCCESS;
3240
3241 } else {
3242 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3243 }
3244
3245 return uReturn;
3246}
3247
3248
3249
3250
3251
Laurence Lundbladec4537442020-04-14 18:53:22 -07003252
3253
3254
Laurence Lundbladee6430642020-03-14 21:15:44 -07003255
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003256typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003257
3258
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003259// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003260static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003262 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003263
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003264 if(uResult != 0) {
3265 /* This loop will run a maximum of 19 times because
3266 * UINT64_MAX < 10 ^^ 19. More than that will cause
3267 * exit with the overflow error
3268 */
3269 for(; nExponent > 0; nExponent--) {
3270 if(uResult > UINT64_MAX / 10) {
3271 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3272 }
3273 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003274 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003275
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003276 for(; nExponent < 0; nExponent++) {
3277 uResult = uResult / 10;
3278 if(uResult == 0) {
3279 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3280 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003281 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003282 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003283 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003284
3285 *puResult = uResult;
3286
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003287 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003288}
3289
3290
Laurence Lundbladee6430642020-03-14 21:15:44 -07003291/* Convert a decimal fraction to an int64_t without using
3292 floating point or math libraries. Most decimal fractions
3293 will not fit in an int64_t and this will error out with
3294 under or overflow
3295 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003296static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003297{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003298 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003299
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003300 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003301
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003302 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003303 * INT64_MAX < 2^31. More than that will cause
3304 * exist with the overflow error
3305 */
3306 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003307 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003308 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003309 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003310 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003311 nExponent--;
3312 }
3313
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003314 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003315 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003316 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3317 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003318 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003319 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003320 }
3321
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003322 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003323
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003324 return QCBOR_SUCCESS;
3325}
3326
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003327/*
3328 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3329 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003330static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3331{
3332 uint64_t uResult;
3333
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003334 // Take the absolute value of the mantissa and convert to unsigned.
3335 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003336 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3337
3338 // Do the exponentiation of the positive mantissa
3339 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3340 if(uReturn) {
3341 return uReturn;
3342 }
3343
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003344
Laurence Lundblade983500d2020-05-14 11:49:34 -07003345 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3346 of INT64_MIN. This assumes two's compliment representation where
3347 INT64_MIN is one increment farther from 0 than INT64_MAX.
3348 Trying to write -INT64_MIN doesn't work to get this because the
3349 compiler tries to work with an int64_t which can't represent
3350 -INT64_MIN.
3351 */
3352 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3353
3354 // Error out if too large
3355 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003356 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3357 }
3358
3359 // Casts are safe because of checks above
3360 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3361
3362 return QCBOR_SUCCESS;
3363}
3364
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003365/*
3366 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3367 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003368static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3369{
3370 if(nMantissa < 0) {
3371 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3372 }
3373
3374 // Cast to unsigned is OK because of check for negative
3375 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3376 // Exponentiation is straight forward
3377 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3378}
3379
3380
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003381#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003382
3383
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003384static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003385{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003386 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003387
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003388 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003389 const uint8_t *pByte = BigNum.ptr;
3390 size_t uLen = BigNum.len;
3391 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003392 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003393 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003395 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396 }
3397
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003398 *pResult = uResult;
3399 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003400}
3401
Laurence Lundblade887add82020-05-17 05:50:34 -07003402static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003403{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003404 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003405}
3406
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003407static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408{
3409 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003410 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3411 if(uError) {
3412 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003413 }
3414 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3415 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003416 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003417}
3418
3419
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003420static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003421{
3422 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003423 /* negaative int furthest from zero is INT64_MIN
3424 which is expressed as -INT64_MAX-1. The value of
3425 a negative bignum is -n-1, one further from zero
3426 than the positive bignum */
3427
3428 /* say INT64_MIN is -2; then INT64_MAX is 1.
3429 Then -n-1 <= INT64_MIN.
3430 Then -n -1 <= -INT64_MAX - 1
3431 THen n <= INT64_MAX. */
3432 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003433 if(uError) {
3434 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003435 }
3436 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003437 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003438 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003439 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003440 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003441}
3442
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003443#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003444
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003445
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003446/*
3447Convert a integers and floats to an int64_t.
3448
3449\param[in] uOptions Bit mask list of conversion options.
3450
3451\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3452
3453\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3454
3455\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3456
3457*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003458static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3459{
3460 switch(pItem->uDataType) {
3461 // TODO: float when ifdefs are set
3462 case QCBOR_TYPE_DOUBLE:
3463 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3464 // TODO: what about under/overflow here?
3465 // Invokes the floating-point HW and/or compiler-added libraries
3466 feclearexcept(FE_ALL_EXCEPT);
3467 *pnValue = llround(pItem->val.dfnum);
3468 if(fetestexcept(FE_INVALID)) {
3469 // TODO: better error code
3470 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3471 }
3472 } else {
3473 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3474 }
3475 break;
3476
3477 case QCBOR_TYPE_INT64:
3478 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3479 *pnValue = pItem->val.int64;
3480 } else {
3481 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3482 }
3483 break;
3484
3485 case QCBOR_TYPE_UINT64:
3486 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3487 if(pItem->val.uint64 < INT64_MAX) {
3488 *pnValue = pItem->val.int64;
3489 } else {
3490 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3491 }
3492 } else {
3493 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3494 }
3495 break;
3496
3497 default:
3498 return QCBOR_ERR_UNEXPECTED_TYPE;
3499 }
3500 return QCBOR_SUCCESS;
3501}
3502
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003503
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003504void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3505 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003506 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003507 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003508{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003509 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003510 return;
3511 }
3512
Laurence Lundbladee6430642020-03-14 21:15:44 -07003513 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003514 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3515 if(uError) {
3516 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003517 return;
3518 }
3519
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003520 if(pItem) {
3521 *pItem = Item;
3522 }
3523
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003524 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003525}
3526
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003527
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003528void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3529 int64_t nLabel,
3530 uint32_t uOptions,
3531 int64_t *pnValue,
3532 QCBORItem *pItem)
3533{
3534 QCBORItem Item;
3535 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3536
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003537 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003538}
3539
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003540
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003541void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3542 const char * szLabel,
3543 uint32_t uOptions,
3544 int64_t *pnValue,
3545 QCBORItem *pItem)
3546{
3547 if(pMe->uLastError != QCBOR_SUCCESS) {
3548 return;
3549 }
3550
3551 QCBORItem Item;
3552 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3553
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003554 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003555}
3556
3557
3558
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003559/*
3560 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003561
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003562 \param[in] uOptions Bit mask list of conversion options.
3563
3564 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3565
3566 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3567
3568 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3569
3570 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003571static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3572{
3573 QCBORError uErr;
3574
3575 switch(pItem->uDataType) {
3576
3577 case QCBOR_TYPE_POSBIGNUM:
3578 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3579 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003580 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003581 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003582 }
3583 break;
3584
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003585 case QCBOR_TYPE_NEGBIGNUM:
3586 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3587 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003588 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003589 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003590 }
3591 break;
3592
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3594 case QCBOR_TYPE_DECIMAL_FRACTION:
3595 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3596 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3597 pItem->val.expAndMantissa.nExponent,
3598 pnValue,
3599 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003600 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3602 }
3603 break;
3604
3605 case QCBOR_TYPE_BIGFLOAT:
3606 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3607 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3608 pItem->val.expAndMantissa.nExponent,
3609 pnValue,
3610 Exponentitate2);
3611 } else {
3612 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3613 }
3614 break;
3615
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003616 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3617 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3618 int64_t nMantissa;
3619 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3620 if(uErr) {
3621 return uErr;
3622 }
3623 return ExponentiateNN(nMantissa,
3624 pItem->val.expAndMantissa.nExponent,
3625 pnValue,
3626 Exponentitate10);
3627 } else {
3628 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3629 }
3630 break;
3631
3632 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3633 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3634 int64_t nMantissa;
3635 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3636 if(uErr) {
3637 return uErr;
3638 }
3639 return ExponentiateNN(nMantissa,
3640 pItem->val.expAndMantissa.nExponent,
3641 pnValue,
3642 Exponentitate10);
3643 } else {
3644 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3645 }
3646 break;
3647
3648 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3649 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3650 int64_t nMantissa;
3651 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3652 if(uErr) {
3653 return uErr;
3654 }
3655 return ExponentiateNN(nMantissa,
3656 pItem->val.expAndMantissa.nExponent,
3657 pnValue,
3658 Exponentitate2);
3659 } else {
3660 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3661 }
3662 break;
3663
3664 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3665 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3666 int64_t nMantissa;
3667 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3668 if(uErr) {
3669 return uErr;
3670 }
3671 return ExponentiateNN(nMantissa,
3672 pItem->val.expAndMantissa.nExponent,
3673 pnValue,
3674 Exponentitate2);
3675 } else {
3676 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003677 }
3678 break;
3679
Laurence Lundbladec4537442020-04-14 18:53:22 -07003680 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003681 return QCBOR_ERR_UNEXPECTED_TYPE;
3682#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003683 }
3684}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003685
3686
Laurence Lundbladec4537442020-04-14 18:53:22 -07003687/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003688 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003689 */
3690void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003691{
3692 QCBORItem Item;
3693
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003694 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003695
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003696 if(pMe->uLastError == QCBOR_SUCCESS) {
3697 // The above conversion succeeded
3698 return;
3699 }
3700
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003701 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003702 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703 return;
3704 }
3705
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003706 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003707}
3708
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003709
3710/*
3711Public function, see header qcbor/qcbor_decode.h file
3712*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003713void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3714{
3715 QCBORItem Item;
3716
3717 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3718
3719 if(pMe->uLastError == QCBOR_SUCCESS) {
3720 // The above conversion succeeded
3721 return;
3722 }
3723
3724 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3725 // The above conversion failed in a way that code below can't correct
3726 return;
3727 }
3728
3729 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3730}
3731
3732
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003733/*
3734Public function, see header qcbor/qcbor_decode.h file
3735*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003736void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3737{
3738 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003739 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3740
3741 if(pMe->uLastError == QCBOR_SUCCESS) {
3742 // The above conversion succeeded
3743 return;
3744 }
3745
3746 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3747 // The above conversion failed in a way that code below can't correct
3748 return;
3749 }
3750
3751 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3752}
3753
3754
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003755static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3756{
3757 switch(pItem->uDataType) {
3758 // TODO: type flaot
3759 case QCBOR_TYPE_DOUBLE:
3760 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3761 feclearexcept(FE_ALL_EXCEPT);
3762 double dRounded = round(pItem->val.dfnum);
3763 // TODO: over/underflow
3764 if(fetestexcept(FE_INVALID)) {
3765 // TODO: better error code
3766 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3767 } else if(isnan(dRounded)) {
3768 // TODO: better error code
3769 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3770 } else if(dRounded >= 0) {
3771 *puValue = (uint64_t)dRounded;
3772 } else {
3773 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3774 }
3775 } else {
3776 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3777 }
3778 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003779
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003780 case QCBOR_TYPE_INT64:
3781 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3782 if(pItem->val.int64 >= 0) {
3783 *puValue = (uint64_t)pItem->val.int64;
3784 } else {
3785 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3786 }
3787 } else {
3788 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3789 }
3790 break;
3791
3792 case QCBOR_TYPE_UINT64:
3793 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3794 *puValue = pItem->val.uint64;
3795 } else {
3796 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3797 }
3798 break;
3799
3800 default:
3801 return QCBOR_ERR_UNEXPECTED_TYPE;
3802 }
3803 return QCBOR_SUCCESS;
3804}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003805
3806
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003807void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3808 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003809 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003810 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003811{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003812 if(pMe->uLastError != QCBOR_SUCCESS) {
3813 return;
3814 }
3815
Laurence Lundbladec4537442020-04-14 18:53:22 -07003816 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003817
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003818 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3819 if(uError) {
3820 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003821 return;
3822 }
3823
Laurence Lundbladea826c502020-05-10 21:07:00 -07003824 if(pItem) {
3825 *pItem = Item;
3826 }
3827
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003828 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003829}
3830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003831
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003832void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3833{
3834 int64_t uValue;
3835 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3836 if(pMe->uLastError != QCBOR_SUCCESS) {
3837 return;
3838 }
3839
3840 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3841 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3842 }
3843}
3844
3845void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3846{
3847 int64_t uValue;
3848 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3849 if(pMe->uLastError != QCBOR_SUCCESS) {
3850 return;
3851 }
3852
3853 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3854 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3855 }
3856}
3857
3858void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3859{
3860 int64_t uValue;
3861 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3862 if(pMe->uLastError != QCBOR_SUCCESS) {
3863 return;
3864 }
3865
3866 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3867 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3868 }
3869}
3870
3871
3872
3873
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003874void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3875 int64_t nLabel,
3876 uint32_t uOptions,
3877 uint64_t *puValue,
3878 QCBORItem *pItem)
3879{
3880 QCBORItem Item;
3881 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3882
3883 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3884}
3885
3886
3887void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3888 const char * szLabel,
3889 uint32_t uOptions,
3890 uint64_t *puValue,
3891 QCBORItem *pItem)
3892{
3893 if(pMe->uLastError != QCBOR_SUCCESS) {
3894 return;
3895 }
3896
3897 QCBORItem Item;
3898 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3899
3900 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3901}
3902
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003903/*
3904 Public function, see header qcbor/qcbor_decode.h file
3905*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003906static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3907{
3908 QCBORError uErr;
3909
3910 switch(pItem->uDataType) {
3911
3912 case QCBOR_TYPE_POSBIGNUM:
3913 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3914 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3915 } else {
3916 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3917 }
3918 break;
3919
3920 case QCBOR_TYPE_NEGBIGNUM:
3921 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3922 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3923 } else {
3924 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3925 }
3926 break;
3927
3928#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3929
3930 case QCBOR_TYPE_DECIMAL_FRACTION:
3931 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3932 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3933 pItem->val.expAndMantissa.nExponent,
3934 puValue,
3935 Exponentitate10);
3936 } else {
3937 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3938 }
3939 break;
3940
3941 case QCBOR_TYPE_BIGFLOAT:
3942 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3943 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3944 pItem->val.expAndMantissa.nExponent,
3945 puValue,
3946 Exponentitate2);
3947 } else {
3948 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3949 }
3950 break;
3951
3952 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3953 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3954 // TODO: Would be better to convert to unsigned
3955 int64_t nMantissa;
3956 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3957 if(uErr != QCBOR_SUCCESS) {
3958 return uErr;
3959 }
3960 return ExponentitateNU(nMantissa,
3961 pItem->val.expAndMantissa.nExponent,
3962 puValue,
3963 Exponentitate10);
3964 } else {
3965 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3966 }
3967 break;
3968
3969 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3970 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3971 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3972 } else {
3973 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3974 }
3975 break;
3976
3977 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3978 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3979 // TODO: Would be better to convert to unsigned
3980 int64_t nMantissa;
3981 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3982 if(uErr != QCBOR_SUCCESS) {
3983 return uErr;
3984 }
3985 return ExponentitateNU(nMantissa,
3986 pItem->val.expAndMantissa.nExponent,
3987 puValue,
3988 Exponentitate2);
3989 } else {
3990 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3991 }
3992 break;
3993
3994 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3995 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3996 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3997 } else {
3998 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3999 }
4000 break;
4001#endif
4002 default:
4003 return QCBOR_ERR_UNEXPECTED_TYPE;
4004 }
4005}
4006
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004007/*
4008 Public function, see header qcbor/qcbor_decode.h file
4009*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004010void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004011{
4012 QCBORItem Item;
4013
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004014 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004015
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004016 if(pMe->uLastError == QCBOR_SUCCESS) {
4017 // The above conversion succeeded
4018 return;
4019 }
4020
4021 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4022 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004023 return;
4024 }
4025
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004026 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004027}
4028
Laurence Lundbladec4537442020-04-14 18:53:22 -07004029
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004030/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004031 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004032*/
4033void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4034{
4035 QCBORItem Item;
4036
4037 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4038
4039 if(pMe->uLastError == QCBOR_SUCCESS) {
4040 // The above conversion succeeded
4041 return;
4042 }
4043
4044 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4045 // The above conversion failed in a way that code below can't correct
4046 return;
4047 }
4048
4049 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4050}
4051
4052
4053/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004054 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004055*/
4056void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4057{
4058 QCBORItem Item;
4059 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4060
4061 if(pMe->uLastError == QCBOR_SUCCESS) {
4062 // The above conversion succeeded
4063 return;
4064 }
4065
4066 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4067 // The above conversion failed in a way that code below can't correct
4068 return;
4069 }
4070
4071 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4072}
4073
4074
4075static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4076{
4077 switch(pItem->uDataType) {
4078 // TODO: float when ifdefs are set
4079 case QCBOR_TYPE_DOUBLE:
4080 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4081 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4082 *pdValue = pItem->val.dfnum;
4083 } else {
4084 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4085 }
4086 }
4087 break;
4088
4089 case QCBOR_TYPE_INT64:
4090 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4091 // TODO: how does this work?
4092 *pdValue = (double)pItem->val.int64;
4093
4094 } else {
4095 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4096 }
4097 break;
4098
4099 case QCBOR_TYPE_UINT64:
4100 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4101 *pdValue = (double)pItem->val.uint64;
4102 } else {
4103 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4104 }
4105 break;
4106
4107 default:
4108 return QCBOR_ERR_UNEXPECTED_TYPE;
4109 }
4110
4111 return QCBOR_SUCCESS;
4112}
4113
4114
4115
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004116void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4117 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004119 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004120{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004121 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004122 return;
4123 }
4124
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004125 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004126
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004127 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004128 if(uError) {
4129 pMe->uLastError = (uint8_t)uError;
4130 return;
4131 }
4132
4133 if(pItem) {
4134 *pItem = Item;
4135 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004136
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004137 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004138}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004139
Laurence Lundbladec4537442020-04-14 18:53:22 -07004140
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004141void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4142 int64_t nLabel,
4143 uint32_t uOptions,
4144 double *pdValue,
4145 QCBORItem *pItem)
4146{
4147 QCBORItem Item;
4148 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4149
4150 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4151}
4152
4153void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4154 const char * szLabel,
4155 uint32_t uOptions,
4156 double *pdValue,
4157 QCBORItem *pItem)
4158{
4159 if(pMe->uLastError != QCBOR_SUCCESS) {
4160 return;
4161 }
4162
4163 QCBORItem Item;
4164 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4165
4166 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4167}
4168
4169
4170
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004171static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4172{
4173 double dResult;
4174
4175 dResult = 0.0;
4176 const uint8_t *pByte = BigNum.ptr;
4177 size_t uLen = BigNum.len;
4178 /* This will overflow and become the float value INFINITY if the number
4179 is too large to fit. No error will be logged.
4180 TODO: should an error be logged? */
4181 while(uLen--) {
4182 dResult = (dResult * 256.0) + (double)*pByte++;
4183 }
4184
4185 return dResult;
4186}
4187
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004188static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004189{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004190 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004191 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4192
4193 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004194 switch(pItem->uDataType) {
4195 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004196
4197#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004198 case QCBOR_TYPE_DECIMAL_FRACTION:
4199 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4200 // TODO: rounding and overflow errors
4201 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4202 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4203 } else {
4204 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4205 }
4206 break;
4207
4208 case QCBOR_TYPE_BIGFLOAT:
4209 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4210 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4211 exp2((double)pItem->val.expAndMantissa.nExponent);
4212 } else {
4213 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4214 }
4215 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004216#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217
4218 case QCBOR_TYPE_POSBIGNUM:
4219 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4220 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4221 } else {
4222 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4223 }
4224 break;
4225
4226 case QCBOR_TYPE_NEGBIGNUM:
4227 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004228 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004229 } else {
4230 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4231 }
4232 break;
4233
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004234#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004235 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4236 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4237 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4238 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4239 } else {
4240 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4241 }
4242 break;
4243
4244 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4245 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4246 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4247 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4248 } else {
4249 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4250 }
4251 break;
4252
4253 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4254 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4255 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4256 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4257 } else {
4258 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4259 }
4260 break;
4261
4262 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4263 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004264 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004265 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4266 } else {
4267 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4268 }
4269 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004270#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4271
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272
4273 default:
4274 return QCBOR_ERR_UNEXPECTED_TYPE;
4275 }
4276
4277 return QCBOR_SUCCESS;
4278}
4279
4280
4281/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004282 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004283*/
4284void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4285{
4286
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004287 QCBORItem Item;
4288
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004289 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004290
4291 if(pMe->uLastError == QCBOR_SUCCESS) {
4292 // The above conversion succeeded
4293 return;
4294 }
4295
4296 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4297 // The above conversion failed in a way that code below can't correct
4298 return;
4299 }
4300
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004301 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004302}
4303
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004304
4305/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004306 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004307*/
4308void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4309{
4310 QCBORItem Item;
4311
4312 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4313
4314 if(pMe->uLastError == QCBOR_SUCCESS) {
4315 // The above conversion succeeded
4316 return;
4317 }
4318
4319 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4320 // The above conversion failed in a way that code below can't correct
4321 return;
4322 }
4323
4324 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4325}
4326
4327
4328/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004329 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004330*/
4331void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4332{
4333 QCBORItem Item;
4334 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4335
4336 if(pMe->uLastError == QCBOR_SUCCESS) {
4337 // The above conversion succeeded
4338 return;
4339 }
4340
4341 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4342 // The above conversion failed in a way that code below can't correct
4343 return;
4344 }
4345
4346 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4347}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004348
4349
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004350#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004351void FarfDecimalFraction(QCBORDecodeContext *pMe,
4352 uint8_t uTagRequirement,
4353 QCBORItem *pItem,
4354 int64_t *pnMantissa,
4355 int64_t *pnExponent)
4356{
4357 QCBORError uErr;
4358
4359 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4360 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4361 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4362 return;
4363 }
4364 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4365 if(uErr != QCBOR_SUCCESS) {
4366 pMe->uLastError = (uint8_t)uErr;
4367 return;
4368 }
4369 }
4370
4371 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4372 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4373 return;
4374 }
4375
4376 switch (pItem->uDataType) {
4377
4378 case QCBOR_TYPE_DECIMAL_FRACTION:
4379 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4380 *pnExponent = pItem->val.expAndMantissa.nExponent;
4381 break;
4382
4383 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4384 *pnExponent = pItem->val.expAndMantissa.nExponent;
4385
4386 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4387 if(uErr != QCBOR_SUCCESS) {
4388 pMe->uLastError = (uint8_t)uErr;
4389 }
4390 break;
4391
4392 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4393 *pnExponent = pItem->val.expAndMantissa.nExponent;
4394
4395 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4396 if(uErr != QCBOR_SUCCESS) {
4397 pMe->uLastError = (uint8_t)uErr;
4398 }
4399 break;
4400
4401 default:
4402 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4403 }
4404}
4405
4406void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4407 uint8_t uTagRequirement,
4408 int64_t nLabel,
4409 int64_t *pnMantissa,
4410 int64_t *pnExponent)
4411{
4412 QCBORItem Item;
4413
4414 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4415 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4416}
4417
4418
4419
4420void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4421 uint8_t uTagRequirement,
4422 const char *szLabel,
4423 int64_t *pnMantissa,
4424 int64_t *pnExponent)
4425{
4426 QCBORItem Item;
4427
4428 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4429
4430 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4431}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004432#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004433
4434
4435UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4436{
4437 while(uInt & 0xff0000000000UL) {
4438 uInt = uInt << 8;
4439 };
4440
4441 UsefulOutBuf UOB;
4442
4443 UsefulOutBuf_Init(&UOB, Buffer);
4444
4445 while(uInt) {
4446 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4447 uInt = uInt << 8;
4448 }
4449
4450 return UsefulOutBuf_OutUBuf(&UOB);
4451}
4452
4453
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004454#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4455
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004456void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4457 uint8_t uTagRequirement,
4458 int64_t nLabel,
4459 UsefulBuf pBufferForMantissa,
4460 UsefulBufC *pMantissa,
4461 bool *pbIsNegative,
4462 int64_t *pnExponent)
4463{
4464 QCBORItem Item;
4465 QCBORError uErr;
4466
4467 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4468
4469 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4470 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4471 if(uErr != QCBOR_SUCCESS) {
4472 pMe->uLastError = (uint8_t)uErr;
4473 return;
4474 }
4475 }
4476
4477 uint64_t uMantissa;
4478
4479 switch (Item.uDataType) {
4480
4481 case QCBOR_TYPE_DECIMAL_FRACTION:
4482 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4483 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4484 *pbIsNegative = false;
4485 } else {
4486 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4487 *pbIsNegative = true;
4488 }
4489 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4490 *pnExponent = Item.val.expAndMantissa.nExponent;
4491 break;
4492
4493 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4494 *pnExponent = Item.val.expAndMantissa.nExponent;
4495 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4496 *pbIsNegative = false;
4497 break;
4498
4499 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4500 *pnExponent = Item.val.expAndMantissa.nExponent;
4501 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4502 *pbIsNegative = true;
4503 break;
4504
4505 default:
4506 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4507 }
4508}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004509#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */