blob: 92e430c97784bc23be80e276fe0a4ed37c34d36f [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 Lundbladeee851742020-01-08 08:37:05 -080046/*===========================================================================
47 DecodeNesting -- Functions for tracking array/map nesting when decoding
48
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080049 See qcbor/qcbor_decode.h for definition of the object
50 used here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080051 ===========================================================================*/
52
Laurence Lundblade9c905e82020-04-25 11:31:38 -070053
54
55/*
56The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
57formed by intermediate nodes (arrays and maps). The cursor for the traversal
58 is the byte offset in the encoded input and a leaf counter for definite
59 length maps and arrays. Indefinite length maps and arrays are handled
60 by look ahead for the break.
61
62 The view presented to the caller has tags, labels and the chunks of
63 indefinite length strings aggregated into one decorated data item.
64
65The caller understands the nesting level in pre-order traversal by
66 the fact that a data item that is a map or array is presented to
67 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
68 and the nesting level of the next item.
69
70 The caller traverse maps and arrays in a special mode that often more convenient
71 that tracking by nesting level. When an array or map is expected or encountered
72 the EnterMap or EnteryArray can be called.
73
74 When entering a map or array like this, the cursor points to the first
75 item in the map or array. When exiting, it points to the item after
76 the map or array, regardless of whether the items in the map or array were
77 all traversed.
78
79 When in a map or array, the cursor functions as normal, but traversal
80 cannot go past the end of the map or array that was entered. If this
81 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
82 go past the end of the map or array ExitMap() or ExitArray() must
83 be called. It can be called any time regardless of the position
84 of the cursor.
85
86 When a map is entered, a special function allows fetching data items
87 by label. This call will traversal the whole map looking for the
88 labeled item. The whole map is traversed so as to detect duplicates.
89 This type of fetching items does not affect the normal traversal
90 cursor.
91
92
93
94
95
96
97
98
99
100
101When a data item is presented to the caller, the nesting level of the data
102 item is presented along with the nesting level of the item that would be
103 next consumed.
104
105
106
107
108
109
110
111
112
113 */
114
Laurence Lundblade6b249302020-04-30 12:38:12 -0700115inline static bool
116// TODO: test Map as array better?
Laurence Lundbladeee851742020-01-08 08:37:05 -0800117IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118{
Laurence Lundblade6b249302020-04-30 12:38:12 -0700119 return uDataType == QCBOR_TYPE_MAP ||
120 uDataType == QCBOR_TYPE_ARRAY ||
121 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122}
123
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124
125inline static uint8_t
126DecodeNesting_GetLevel(const QCBORDecodeNesting *pNesting)
127{
128 // Check in DecodeNesting_Descend and never having
129 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
130 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
131}
132
133
134inline static bool InBoundMode(const QCBORDecodeNesting *pNesting)
135{
136 return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_BOUND;
137}
138
139/*inline static bool IsArray(const QCBORDecodeNesting *pNesting)
140{
141 const unsigned uIndex = DecodeNesting_GetLevel(pNesting);
142
143 return (0x01ULL << ((uIndex * 3) + 1)) & pNesting->uTypeBitMap;
144}
145
146inline static bool IsBstr(const QCBORDecodeNesting *pNesting)
147{
148 const unsigned uIndex = DecodeNesting_GetLevel(pNesting);
149
150 return (0x01ULL << ((uIndex * 3) + 2)) & pNesting->uTypeBitMap;
151}*/
152
153
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700154inline static bool
155DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700157 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
158 return true;
159 } else {
160 return false;
161 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700162}
163
Laurence Lundblade937ea812020-05-08 11:38:23 -0700164// Determine if at the end of a map or array while in map mode
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700165inline static bool
166DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
167{
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700168 if(pNesting->pCurrentMap && InBoundMode(pNesting)) {
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700169 if(pNesting->pCurrentMap->uCount == 0) {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700170 // TODO: won't work for indefinite length
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700171 // In map mode and consumed all items, so it is the end
172 return true;
173 } else {
174 // In map mode, all items not consumed, so it is NOT the end
175 return false;
176 }
177 } else {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700178 // Not in map mode. The end is determined in other ways.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700179 return false;
180 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700181}
182
183
Laurence Lundbladeee851742020-01-08 08:37:05 -0800184inline static int
185DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700186{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700187 return pNesting->pCurrent->uCount == UINT16_MAX;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700188 //return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_INDEFINITE;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700189}
190
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700191inline static int
192DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
193{
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700194 return (bool)InBoundMode(pNesting);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700195}
196
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700197
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700199inline static uint8_t
200DecodeNesting_GetMapModeLevel(QCBORDecodeNesting *pNesting)
201{
202 // Check in DecodeNesting_Descend and never having
203 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
204 return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0]));
205}
206
Laurence Lundbladeee851742020-01-08 08:37:05 -0800207inline static int
208DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700209{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700210 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700211 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700212 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800213
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700214 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
215}
216
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800217// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800218inline static QCBORError
219DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700220{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800221 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700222 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800223 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700224 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800225
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800226 // breaks can only occur when the map/array is indefinite length
227 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
228 return QCBOR_ERR_BAD_BREAK;
229 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800230
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800231 // if all OK, the break reduces the level of nesting
232 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800233
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800234 return QCBOR_SUCCESS;
235}
236
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700237// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700238/* Decrements the map/array counter if possible. If decrement
239 closed out a map or array, then level up in nesting and decrement
240 again, until, the top is reached or the end of a map mode is reached
241 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800242inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700243DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800244{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700245 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700246 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800247
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800248 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700249 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800250 pNesting->pCurrent->uCount--;
251 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700252
253 if(pNesting->pCurrent->uCount != 0) {
254 // Did not close out an array or map, so nothing further
255 break;
256 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700258 if(InBoundMode(pNesting)) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700259 // In map mode the level-up must be done explicitly
260 break;
261 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700262
263 // Closed out an array or map so level up
264 pNesting->pCurrent--;
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700265 /*if(pNesting->pCurrent->uMapMode) {
266 // Bring the current map level along if new level is a map
267 // TODO: must search up until a mapmode level is found.
268 pNesting->pCurrentMap = pNesting->pCurrent;
269 } */
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700270
271 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700272 }
273}
274
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700275inline static void
276DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
277{
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700278 /* Have descended into this is called. The job here is just to mark it in bounded mode */
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700279 pNesting->pCurrentMap = pNesting->pCurrent;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700280 pNesting->pCurrentMap->uType |= QCBOR_NEST_TYPE_IS_BOUND;
281 // Cast to uint32_t is safe because QCBOR restricts encoded input to < UINT32_MAX
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700282 pNesting->pCurrentMap->uOffset = (uint32_t)uOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700283}
284
285inline static void
286DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
287{
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700288 pNesting->pCurrentMap->uType &= ~QCBOR_NEST_TYPE_IS_BOUND;
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700289 pNesting->pCurrent = pNesting->pCurrentMap - 1; // TODO error check
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700290
291 DecodeNesting_DecrementCount(pNesting);
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700292
293 while(1) {
294 pNesting->pCurrentMap--;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700295 if(InBoundMode(pNesting)) {
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700296 break;
297 }
298 if(pNesting->pCurrentMap == &(pNesting->pMapsAndArrays[0])) {
299 break;
300 }
301 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700302}
303
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800304// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800305inline static QCBORError
306DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700307{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700308 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800309
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800310 if(pItem->val.uCount == 0) {
311 // Nothing to do for empty definite lenth arrays. They are just are
312 // effectively the same as an item that is not a map or array
313 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530314 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800315 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800316
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800317 // Error out if arrays is too long to handle
318 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700319 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
320 goto Done;
321 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800322
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800323 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700324 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
325 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
326 goto Done;
327 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800328
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800329 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700330 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800331
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800332 // Record a few details for this nesting level
333 pNesting->pCurrent->uMajorType = pItem->uDataType;
334 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700335 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700336 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800337
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700338Done:
339 return nReturn;;
340}
341
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700342inline static QCBORError
343DecodeNesting_Descend2(QCBORDecodeNesting *pNesting, uint8_t uQCBORType, uint64_t uCount, uint32_t uEndOffset)
344{
345 QCBORError nReturn = QCBOR_SUCCESS;
346
347 if(uCount == 0) {
348 // Nothing to do for empty definite lenth arrays. They are just are
349 // effectively the same as an item that is not a map or array
350 goto Done;
351 // Empty indefinite length maps and arrays are handled elsewhere
352 }
353
354 // Error out if arrays is too long to handle
355 if(uCount != UINT16_MAX && uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
356 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
357 goto Done;
358 }
359
360 // Error out if nesting is too deep
361 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
362 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
363 goto Done;
364 }
365
366 // The actual descend
367 pNesting->pCurrent++;
368
369 // Fill in the new level fully
370 pNesting->pCurrent->uMajorType = uQCBORType;
371 pNesting->pCurrent->uCount = (uint16_t)uCount;
372 pNesting->pCurrent->uSaveCount = (uint16_t)uCount;
373 pNesting->pCurrent->uEndOffset = uEndOffset;
374 pNesting->pCurrent->uMapMode = 0;
375
376Done:
377 return nReturn;;
378}
379
380
381
Laurence Lundbladeee851742020-01-08 08:37:05 -0800382inline static void
383DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700384{
385 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
386}
387
388
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700389static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
390{
391 *pSave = *pNesting;
392 pNesting->pCurrent = pNesting->pCurrentMap;
393
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700394 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700395 pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount;
396 }
397}
398
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700399static inline void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700400{
401 *pNesting = *pSave;
402}
403
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700404inline static QCBORError DecodeNesting_EnterBstr(QCBORDecodeNesting *pNesting, uint32_t uEndOffset)
405{
406 QCBORError uReturn ;
407
408 // Error out if nesting is too deep
409 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
410 uReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
411 goto Done;
412 }
413
414 // The actual descend
415 pNesting->pCurrent++;
416
417 // Record a few details for this nesting level
418 pNesting->pCurrent->uMajorType = 1; // TODO the right value for a bstr
419 pNesting->pCurrent->uCount = 0xffff;
420 pNesting->pCurrent->uSaveCount = 0xffff;
421 pNesting->pCurrent->uType = 0;
422
423 uReturn = QCBOR_SUCCESS;
424
425Done:
426 return uReturn;
427
428
429}
430
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700431
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700432
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700433
Laurence Lundbladeee851742020-01-08 08:37:05 -0800434/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800435 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
436
437 The following four functions are pretty wrappers for invocation of
438 the string allocator supplied by the caller.
439
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800441
Laurence Lundbladeee851742020-01-08 08:37:05 -0800442static inline void
443StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800444{
445 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
446}
447
Laurence Lundbladeee851742020-01-08 08:37:05 -0800448// StringAllocator_Reallocate called with pMem NULL is
449// equal to StringAllocator_Allocate()
450static inline UsefulBuf
451StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
452 void *pMem,
453 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800454{
455 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
456}
457
Laurence Lundbladeee851742020-01-08 08:37:05 -0800458static inline UsefulBuf
459StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800460{
461 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
462}
463
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464static inline void
465StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800466{
467 if(pMe->pfAllocator) {
468 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
469 }
470}
471
472
473
Laurence Lundbladeee851742020-01-08 08:37:05 -0800474/*===========================================================================
475 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700476
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800477 See qcbor/qcbor_decode.h for definition of the object
478 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800479 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700480/*
481 Public function, see header file
482 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800483void QCBORDecode_Init(QCBORDecodeContext *me,
484 UsefulBufC EncodedCBOR,
485 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700486{
487 memset(me, 0, sizeof(QCBORDecodeContext));
488 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800489 // Don't bother with error check on decode mode. If a bad value is
490 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700491 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700492 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700493 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
494 me->auMappedTags[i] = 0xffff;
495 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700496}
497
498
499/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700500 Public function, see header file
501 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
503 QCBORStringAllocate pfAllocateFunction,
504 void *pAllocateContext,
505 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700506{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800507 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
508 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
509 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700510}
511
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
513/*
514 Public function, see header file
515 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
517 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700518{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700519 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700520}
521
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700522
523/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800524 This decodes the fundamental part of a CBOR data item, the type and
525 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800526
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529 This does the network->host byte order conversion. The conversion
530 here also results in the conversion for floats in addition to that
531 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800532
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700533 This returns:
534 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800536 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 tags and floats and length for strings and arrays
538
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800539 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800541
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800542 The int type is preferred to uint8_t for some variables as this
543 avoids integer promotions, can reduce code size and makes
544 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800546inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
547 int *pnMajorType,
548 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800549 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700550{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700551 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800554 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800557 const int nTmpMajorType = nInitialByte >> 5;
558 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800559
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800560 // Where the number or argument accumulates
561 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800562
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800563 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700564 // Need to get 1,2,4 or 8 additional argument bytes. Map
565 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800566 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800567
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800568 // Loop getting all the bytes in the argument
569 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800570 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800571 // This shift and add gives the endian conversion
572 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
573 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800574 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800575 // The reserved and thus-far unused additional info values
576 nReturn = QCBOR_ERR_UNSUPPORTED;
577 goto Done;
578 } else {
579 // Less than 24, additional info is argument or 31, an indefinite length
580 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800581 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584 if(UsefulInputBuf_GetError(pUInBuf)) {
585 nReturn = QCBOR_ERR_HIT_END;
586 goto Done;
587 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800588
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700589 // All successful if we got here.
590 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800591 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800592 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800593 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595Done:
596 return nReturn;
597}
598
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800599
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 CBOR doesn't explicitly specify two's compliment for integers but all
602 CPUs use it these days and the test vectors in the RFC are so. All
603 integers in the CBOR structure are positive and the major type
604 indicates positive or negative. CBOR can express positive integers
605 up to 2^x - 1 where x is the number of bits and negative integers
606 down to 2^x. Note that negative numbers can be one more away from
607 zero than positive. Stdint, as far as I can tell, uses two's
608 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 used carefully here, and in particular why it isn't used in the interface.
612 Also see
613 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
614
615 Int is used for values that need less than 16-bits and would be subject
616 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800618inline static QCBORError
619DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700621 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
624 if (uNumber <= INT64_MAX) {
625 pDecodedItem->val.int64 = (int64_t)uNumber;
626 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 } else {
629 pDecodedItem->val.uint64 = uNumber;
630 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800631
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 }
633 } else {
634 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800635 // CBOR's representation of negative numbers lines up with the
636 // two-compliment representation. A negative integer has one
637 // more in range than a positive integer. INT64_MIN is
638 // equal to (-INT64_MAX) - 1.
639 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800641
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 } else {
643 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000644 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 nReturn = QCBOR_ERR_INT_OVERFLOW;
646 }
647 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800648
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 return nReturn;
650}
651
652// Make sure #define value line up as DecodeSimple counts on this.
653#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
654#error QCBOR_TYPE_FALSE macro value wrong
655#endif
656
657#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
658#error QCBOR_TYPE_TRUE macro value wrong
659#endif
660
661#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
662#error QCBOR_TYPE_NULL macro value wrong
663#endif
664
665#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
666#error QCBOR_TYPE_UNDEF macro value wrong
667#endif
668
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700669#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
670#error QCBOR_TYPE_BREAK macro value wrong
671#endif
672
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700673#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
674#error QCBOR_TYPE_DOUBLE macro value wrong
675#endif
676
677#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
678#error QCBOR_TYPE_FLOAT macro value wrong
679#endif
680
681/*
682 Decode true, false, floats, break...
683 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800684inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800685DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700687 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800688
Laurence Lundbladeee851742020-01-08 08:37:05 -0800689 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800690 // above make sure uAdditionalInfo values line up with uDataType values.
691 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
692 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800695 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
696 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700698 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700699 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
700 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700701 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700702 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700703 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
704 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700705 break;
706 case DOUBLE_PREC_FLOAT:
707 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700708 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700709 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800710
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 case CBOR_SIMPLEV_FALSE: // 20
712 case CBOR_SIMPLEV_TRUE: // 21
713 case CBOR_SIMPLEV_NULL: // 22
714 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700715 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700716 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800717
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 case CBOR_SIMPLEV_ONEBYTE: // 24
719 if(uNumber <= CBOR_SIMPLE_BREAK) {
720 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700721 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 goto Done;
723 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800724 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 default: // 0-19
728 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800729 /*
730 DecodeTypeAndNumber will make uNumber equal to
731 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
732 safe because the 2, 4 and 8 byte lengths of uNumber are in
733 the double/float cases above
734 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 pDecodedItem->val.uSimple = (uint8_t)uNumber;
736 break;
737 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739Done:
740 return nReturn;
741}
742
743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530745 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800747inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
748 int nMajorType,
749 uint64_t uStrLen,
750 UsefulInputBuf *pUInBuf,
751 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700752{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700753 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800755 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
756 // This check makes the casts to size_t below safe.
757
758 // 4 bytes less than the largest sizeof() so this can be tested by
759 // putting a SIZE_MAX length in the CBOR test input (no one will
760 // care the limit on strings is 4 bytes shorter).
761 if(uStrLen > SIZE_MAX-4) {
762 nReturn = QCBOR_ERR_STRING_TOO_LONG;
763 goto Done;
764 }
765
766 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530767 if(UsefulBuf_IsNULLC(Bytes)) {
768 // Failed to get the bytes for this string item
769 nReturn = QCBOR_ERR_HIT_END;
770 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700771 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530772
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800773 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530774 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800775 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530776 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700777 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530778 goto Done;
779 }
780 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800781 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530782 } else {
783 // Normal case with no string allocator
784 pDecodedItem->val.string = Bytes;
785 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800786 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800787 // Cast because ternary operator causes promotion to integer
788 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
789 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530791Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 return nReturn;
793}
794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800796
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797
798
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799
800
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801// Make sure the constants align as this is assumed by
802// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700803#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
804#error QCBOR_TYPE_ARRAY value not lined up with major type
805#endif
806#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
807#error QCBOR_TYPE_MAP value not lined up with major type
808#endif
809
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800811 This gets a single data item and decodes it including preceding
812 optional tagging. This does not deal with arrays and maps and nesting
813 except to decode the data item introducing them. Arrays and maps are
814 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800815
Laurence Lundbladeee851742020-01-08 08:37:05 -0800816 Errors detected here include: an array that is too long to decode,
817 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800819static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
820 QCBORItem *pDecodedItem,
821 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700822{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700823 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800824
Laurence Lundbladeee851742020-01-08 08:37:05 -0800825 /*
826 Get the major type and the number. Number could be length of more
827 bytes or the value depending on the major type nAdditionalInfo is
828 an encoding of the length of the uNumber and is needed to decode
829 floats and doubles
830 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800831 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700832 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800833 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800834
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700835 memset(pDecodedItem, 0, sizeof(QCBORItem));
836
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800837 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladeee851742020-01-08 08:37:05 -0800839 // Error out here if we got into trouble on the type and number. The
840 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700841 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700843 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800844
Laurence Lundbladeee851742020-01-08 08:37:05 -0800845 // At this point the major type and the value are valid. We've got
846 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800847 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
849 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700851 nReturn = QCBOR_ERR_BAD_INT;
852 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700854 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700857 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
858 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800859 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
860 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
861 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
862 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530863 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800865 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866 }
867 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800868
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
870 case CBOR_MAJOR_TYPE_MAP: // Major type 5
871 // Record the number of items in the array or map
872 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
873 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
874 goto Done;
875 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530877 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800879 // type conversion OK because of check above
880 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800882 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800883 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
884 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800888 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700889 nReturn = QCBOR_ERR_BAD_INT;
890 } else {
891 pDecodedItem->val.uTagV = uNumber;
892 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
893 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundbladeee851742020-01-08 08:37:05 -0800896 case CBOR_MAJOR_TYPE_SIMPLE:
897 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800898 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800900
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901 default:
902 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 nReturn = QCBOR_ERR_UNSUPPORTED;
904 break;
905 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700907Done:
908 return nReturn;
909}
910
911
912
913/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800914 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800915 individual chunk items together into one QCBORItem using the string
916 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800917
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530918 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700919 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800920static inline QCBORError
921GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700923 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700924
925 // Get pointer to string allocator. First use is to pass it to
926 // GetNext_Item() when option is set to allocate for *every* string.
927 // Second use here is to allocate space to coallese indefinite
928 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800929 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
930 &(me->StringAllocator) :
931 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700933 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800934 nReturn = GetNext_Item(&(me->InBuf),
935 pDecodedItem,
936 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 if(nReturn) {
938 goto Done;
939 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700941 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530942 // code in this function from here down can be eliminated. Run tests, except
943 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800945 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700946 const uint8_t uStringType = pDecodedItem->uDataType;
947 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 goto Done; // no need to do any work here on non-string types
949 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800951 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530952 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800953 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530956 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800957 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
959 goto Done;
960 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700962 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700963 UsefulBufC FullString = NULLUsefulBufC;
964
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700966 // Get item for next chunk
967 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700968 // NULL string allocator passed here. Do not need to allocate
969 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800970 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700971 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700972 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700973 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530975 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700976 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800977 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530979 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700980 break;
981 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700983 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530984 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700985 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(StringChunkItem.uDataType != uStringType ||
987 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700988 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989 break;
990 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800993 // The first time throurgh FullString.ptr is NULL and this is
994 // equivalent to StringAllocator_Allocate()
995 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
996 UNCONST_POINTER(FullString.ptr),
997 FullString.len + StringChunkItem.val.string.len);
998
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301000 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001001 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 break;
1003 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001004
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001005 // Copy new string chunk at the end of string so far.
1006 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001009 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1010 // Getting the item failed, clean up the allocated memory
1011 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001014Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015 return nReturn;
1016}
1017
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001018
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001019uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1020 if(uTagVal < 0xfff0) {
1021 return uTagVal;
1022 } else {
1023 // TODO constant and error check
1024 int x = uTagVal - 0xfff0;
1025 return me->auMappedTags[x];
1026 }
1027}
1028
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001030 Gets all optional tag data items preceding a data item that is not an
1031 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001032 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001033static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001034GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001035{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001036 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001037 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001038
1039 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {0xffff, 0xffff, 0xffff, 0xffff};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001040
Laurence Lundblade59289e52019-12-30 13:44:37 -08001041 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001042 for(;;) {
1043 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001044 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001045 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001046 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001047
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001048 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1049 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001050 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001051 break;
1052 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001054 // Is there room for the tag in the tags list?
1055 size_t uTagIndex;
1056 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1057 if(auTags[uTagIndex] == 0xffff) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001058 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001059 }
1060 }
1061 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
1062 return 99; // TODO error code
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001063 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001065 // Is the tag > 16 bits?
1066 if(pDecodedItem->val.uTagV > 0xffff) {
1067 size_t uTagMapIndex;
1068 // Is there room in the tag map?
1069 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1070 if(me->auMappedTags[uTagMapIndex] == 0xffff) {
1071 break;
1072 }
1073 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1074 break;
1075 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001076 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001077 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1078 // No room for the tag
1079 return 97; // TODO error code
1080 }
1081
1082 // Cover the case where tag is new and were it is already in the map
1083 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
1084 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast
1085
1086 } else {
1087 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001088 }
1089 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001091Done:
1092 return nReturn;
1093}
1094
1095
1096/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001097 This layer takes care of map entries. It combines the label and data
1098 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001099 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001100static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001101GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001102{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001103 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001104 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001105 if(nReturn)
1106 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001107
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001108 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001109 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001110 goto Done;
1111 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001112
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001113 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1114 // In a map and caller wants maps decoded, not treated as arrays
1115
1116 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1117 // If in a map and the right decoding mode, get the label
1118
Laurence Lundbladeee851742020-01-08 08:37:05 -08001119 // Save label in pDecodedItem and get the next which will
1120 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001121 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001122 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001123 if(nReturn)
1124 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001125
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301126 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001127
1128 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1129 // strings are always good labels
1130 pDecodedItem->label.string = LabelItem.val.string;
1131 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1132 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001133 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001134 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1135 goto Done;
1136 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1137 pDecodedItem->label.int64 = LabelItem.val.int64;
1138 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1139 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1140 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1141 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1142 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1143 pDecodedItem->label.string = LabelItem.val.string;
1144 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1145 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1146 } else {
1147 // label is not an int or a string. It is an arrray
1148 // or a float or such and this implementation doesn't handle that.
1149 // Also, tags on labels are ignored.
1150 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1151 goto Done;
1152 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001153 }
1154 } else {
1155 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001156 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1157 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1158 goto Done;
1159 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001160 // Decoding a map as an array
1161 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001162 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1163 // Cast is needed because of integer promotion
1164 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001165 }
1166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001168Done:
1169 return nReturn;
1170}
1171
1172
1173/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001174 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001175 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001176 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001177static QCBORError
1178QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001179{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001180 // Stack ptr/int: 2, QCBORItem : 64
1181
Laurence Lundblade30816f22018-11-10 13:40:22 +07001182 QCBORError nReturn;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001183 /* === First figure out if at the end of traversal === */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001185 /* Case 1. Out of bytes to consume.
1186
1187 This is either the end of the top-level CBOR that was give
1188 to QCBORDecode_Init() or the end of a tag 24 bstr wrapped CBOR.
1189 It is detected by all bytes being consumed from the UsefulInputBuf.
1190
1191 To go back out of the tag 24 bstr wrapped item, the caller must
1192 explicitly call Exit() which will reset the UsefulInputBuf
1193 to the next highest bstr wrapped or the top level.
1194
1195 This is always the end condition that QCBORDecode_Finish()
1196 considers complete.
1197
1198 TODO: can the DecodeNesting_IsAtTop be removed? QCBORDecode_Finish()
1199 will perform this check.
1200
1201 */
Laurence Lundblade937ea812020-05-08 11:38:23 -07001202 /* For a pre-order traversal a non-error end occurs when there
1203 are no more bytes to consume and the nesting level is at the top.
1204 If it's not at the top, then the CBOR is not well formed. This error
1205 is caught elsewhere.
1206
1207 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001208 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001209 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1210 goto Done;
1211 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001212
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001213
1214 /* Case 2. End of map or array in bounded mode
1215
1216 The caller is attempting traveral of a bounded map or array and
1217 has got to the end of it.
1218
1219 The caller must explicitly exit the bounded mode map or array
1220 to get past this condition.
1221
1222 To complete a decode of the full input CBOR, the caller must
1223 exit all maps and arrays in bounded mode and this is never
1224 the successful end of decoding.
1225
1226 */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001227 /* It is also an end of the input when in map mode and the cursor
Laurence Lundblade937ea812020-05-08 11:38:23 -07001228 is at the end of the map */
1229
1230
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001231 // This is to handle map and array mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001232 if(DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001233 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1234 goto Done;
1235 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001236
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001237 /* === Not at the end; get another item === */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001239 if(nReturn) {
1240 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001241 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301242
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001243 // Breaks ending arrays/maps are always processed at the end of this function.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301244 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301245 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301246 nReturn = QCBOR_ERR_BAD_BREAK;
1247 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001249
Laurence Lundblade6de37062018-10-15 12:22:42 +05301250 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301251 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301252 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001253
Laurence Lundblade6de37062018-10-15 12:22:42 +05301254 // Process the item just received for descent or decrement, and
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001255 // ascend if decrements are enough to close out a definite length array/map
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001256 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount != 0) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001257 // If the new item is array or map, the nesting level descends
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001258 nReturn = DecodeNesting_Descend2(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount, 0L);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001259 // Maps and arrays do count in as items in the map/array that encloses
1260 // them so a decrement needs to be done for them too, but that is done
1261 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001262 // are opened with the exception of an empty map or array.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001263 } else {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001264 /* === Figure out if item got closed out maps or arrays === */
1265
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001266 // Decrement the count of items in the enclosing map/array
1267 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301268 // triggers a decrement in the map/array above that and
1269 // an ascend in nesting level.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001270 while(1) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001271 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001272 if(nReturn) {
1273 goto Done;
1274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001276 // For indefinite length maps/arrays, looking at any and
1277 // all breaks that might terminate them. The equivalent
1278 // for definite length maps/arrays happens in
1279 // DecodeNesting_DecrementCount().
1280 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1281 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1282 // Peek forward one item to see if it is a break.
1283 QCBORItem Peek;
1284 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1285 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1286 if(nReturn) {
1287 goto Done;
1288 }
1289 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1290 // It is not a break, rewind so it can be processed normally.
1291 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1292 break;
1293 }
1294 // It is a break. Ascend one nesting level.
1295 // The break is consumed.
1296 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1297 if(nReturn) {
1298 // break occured outside of an indefinite length array/map
1299 goto Done;
1300 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301301 }
1302 }
1303 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001305
1306 /* === Tell the caller the nest level of the next item === */
1307
Laurence Lundblade6de37062018-10-15 12:22:42 +05301308 // Tell the caller what level is next. This tells them what maps/arrays
1309 // were closed out and makes it possible for them to reconstruct
1310 // the tree with just the information returned by GetNext
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001311 // TODO: pull this into DecodeNesting_GetLevel
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001312 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1313 // At end of a map / array in map mode, so next nest is 0 to
1314 // indicate this end.
1315 pDecodedItem->uNextNestLevel = 0;
1316 } else {
1317 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1318 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001319
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001320Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001321 if(nReturn != QCBOR_SUCCESS) {
1322 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1323 memset(pDecodedItem, 0, sizeof(QCBORItem));
1324 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001325 return nReturn;
1326}
1327
1328
Laurence Lundblade59289e52019-12-30 13:44:37 -08001329/*
1330 Mostly just assign the right data type for the date string.
1331 */
1332inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1333{
1334 // Stack Use: UsefulBuf 1 16
1335 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1336 return QCBOR_ERR_BAD_OPT_TAG;
1337 }
1338
1339 const UsefulBufC Temp = pDecodedItem->val.string;
1340 pDecodedItem->val.dateString = Temp;
1341 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1342 return QCBOR_SUCCESS;
1343}
1344
1345
1346/*
1347 Mostly just assign the right data type for the bignum.
1348 */
1349inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1350{
1351 // Stack Use: UsefulBuf 1 -- 16
1352 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1353 return QCBOR_ERR_BAD_OPT_TAG;
1354 }
1355 const UsefulBufC Temp = pDecodedItem->val.string;
1356 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001357 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001358 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1359 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001360 return QCBOR_SUCCESS;
1361}
1362
1363
1364/*
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001365 Mostly just assign the right data type for the bignum.
1366 */
1367inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1368{
1369 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1370 return QCBOR_ERR_BAD_OPT_TAG;
1371 }
1372 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1373 return QCBOR_SUCCESS;
1374}
1375
1376
1377/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001378 The epoch formatted date. Turns lots of different forms of encoding
1379 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001380 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001381static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001382{
1383 // Stack usage: 1
1384 QCBORError nReturn = QCBOR_SUCCESS;
1385
1386 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1387
1388 switch (pDecodedItem->uDataType) {
1389
1390 case QCBOR_TYPE_INT64:
1391 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1392 break;
1393
1394 case QCBOR_TYPE_UINT64:
1395 if(pDecodedItem->val.uint64 > INT64_MAX) {
1396 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1397 goto Done;
1398 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001399 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001400 break;
1401
1402 case QCBOR_TYPE_DOUBLE:
1403 {
1404 // This comparison needs to be done as a float before
1405 // conversion to an int64_t to be able to detect doubles
1406 // that are too large to fit into an int64_t. A double
1407 // has 52 bits of preceision. An int64_t has 63. Casting
1408 // INT64_MAX to a double actually causes a round up which
1409 // is bad and wrong for the comparison because it will
1410 // allow conversion of doubles that can't fit into a
1411 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1412 // the cutoff point as if that rounds up in conversion to
1413 // double it will still be less than INT64_MAX. 0x7ff is
1414 // picked because it has 11 bits set.
1415 //
1416 // INT64_MAX seconds is on the order of 10 billion years,
1417 // and the earth is less than 5 billion years old, so for
1418 // most uses this conversion error won't occur even though
1419 // doubles can go much larger.
1420 //
1421 // Without the 0x7ff there is a ~30 minute range of time
1422 // values 10 billion years in the past and in the future
1423 // where this this code would go wrong.
1424 const double d = pDecodedItem->val.dfnum;
1425 if(d > (double)(INT64_MAX - 0x7ff)) {
1426 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1427 goto Done;
1428 }
1429 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1430 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1431 }
1432 break;
1433
1434 default:
1435 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1436 goto Done;
1437 }
1438 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1439
1440Done:
1441 return nReturn;
1442}
1443
1444
1445#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1446/*
1447 Decode decimal fractions and big floats.
1448
1449 When called pDecodedItem must be the array that is tagged as a big
1450 float or decimal fraction, the array that has the two members, the
1451 exponent and mantissa.
1452
1453 This will fetch and decode the exponent and mantissa and put the
1454 result back into pDecodedItem.
1455 */
1456inline static QCBORError
1457QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1458{
1459 QCBORError nReturn;
1460
1461 // --- Make sure it is an array; track nesting level of members ---
1462 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1463 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1464 goto Done;
1465 }
1466
1467 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001468 // definite length arrays, but not for indefnite. Instead remember
1469 // the nesting level the two integers must be at, which is one
1470 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001471 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1472
1473 // --- Is it a decimal fraction or a bigfloat? ---
1474 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1475 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1476
1477 // --- Get the exponent ---
1478 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001479 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001480 if(nReturn != QCBOR_SUCCESS) {
1481 goto Done;
1482 }
1483 if(exponentItem.uNestingLevel != nNestLevel) {
1484 // Array is empty or a map/array encountered when expecting an int
1485 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1486 goto Done;
1487 }
1488 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1489 // Data arriving as an unsigned int < INT64_MAX has been converted
1490 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1491 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1492 // will be too large for this to handle and thus an error that will
1493 // get handled in the next else.
1494 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1495 } else {
1496 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1497 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1498 goto Done;
1499 }
1500
1501 // --- Get the mantissa ---
1502 QCBORItem mantissaItem;
1503 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1504 if(nReturn != QCBOR_SUCCESS) {
1505 goto Done;
1506 }
1507 if(mantissaItem.uNestingLevel != nNestLevel) {
1508 // Mantissa missing or map/array encountered when expecting number
1509 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1510 goto Done;
1511 }
1512 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1513 // Data arriving as an unsigned int < INT64_MAX has been converted
1514 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1515 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1516 // will be too large for this to handle and thus an error that
1517 // will get handled in an else below.
1518 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1519 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1520 // Got a good big num mantissa
1521 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1522 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001523 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1524 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1525 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001526 } else {
1527 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1528 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1529 goto Done;
1530 }
1531
1532 // --- Check that array only has the two numbers ---
1533 if(mantissaItem.uNextNestLevel == nNestLevel) {
1534 // Extra items in the decimal fraction / big num
1535 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1536 goto Done;
1537 }
1538
1539Done:
1540
1541 return nReturn;
1542}
1543#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1544
1545
1546/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001547 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001548 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001549QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001550QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001551{
1552 QCBORError nReturn;
1553
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001554 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001555 if(nReturn != QCBOR_SUCCESS) {
1556 goto Done;
1557 }
1558
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001559 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1560 switch(pDecodedItem->uTags[i] ) {
1561 case 0xffff:
1562 // The end of the tag list or no tags
1563 // Successful exit from the loop.
1564 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001565
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001566 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001567 nReturn = DecodeDateString(pDecodedItem);
1568 break;
1569
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001570 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001571 nReturn = DecodeDateEpoch(pDecodedItem);
1572 break;
1573
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001574 case CBOR_TAG_POS_BIGNUM:
1575 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001576 nReturn = DecodeBigNum(pDecodedItem);
1577 break;
1578
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001579 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1580 case CBOR_TAG_DECIMAL_FRACTION:
1581 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001582 // For aggregate tagged types, what goes into pTags is only collected
1583 // from the surrounding data item, not the contents, so pTags is not
1584 // passed on here.
1585
1586 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1587 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001588 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001589
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001590 case CBOR_TAG_BIN_UUID:
1591 nReturn = DecodeUUID(pDecodedItem);
1592
1593 default:
1594 // A tag that is not understood
1595 // A successful exit from the loop
1596 goto Done;
1597
1598 }
1599 if(nReturn != QCBOR_SUCCESS) {
1600 goto Done;
1601 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001602 }
1603
1604Done:
1605 if(nReturn != QCBOR_SUCCESS) {
1606 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1607 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1608 }
1609 return nReturn;
1610}
1611
1612
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001613QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1614{
1615 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1616
1617 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1618
1619 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1620
1621 return uErr;
1622}
1623
1624
Laurence Lundblade59289e52019-12-30 13:44:37 -08001625/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001626 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001627 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001628QCBORError
1629QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1630 QCBORItem *pDecodedItem,
1631 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001632{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001633 QCBORError nReturn;
1634
1635 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1636 if(nReturn != QCBOR_SUCCESS) {
1637 return nReturn;
1638 }
1639
1640 if(pTags != NULL) {
1641 pTags->uNumUsed = 0;
1642 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1643 if(pDecodedItem->uTags[i] == 0xffff) {
1644 break;
1645 }
1646 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1647 return QCBOR_ERR_TOO_MANY_TAGS;
1648 }
1649 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1650 pTags->uNumUsed++;
1651 }
1652 }
1653
1654 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001655}
1656
1657
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001658/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301659 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301660 next one down. If a layer has no work to do for a particular item
1661 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001662
Laurence Lundblade59289e52019-12-30 13:44:37 -08001663 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1664 tagged data items, turning them into the local C representation.
1665 For the most simple it is just associating a QCBOR_TYPE with the data. For
1666 the complex ones that an aggregate of data items, there is some further
1667 decoding and a little bit of recursion.
1668
1669 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301670 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301671 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001672 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001673
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301674 - GetNext_MapEntry -- This handles the combining of two
1675 items, the label and the data, that make up a map entry.
1676 It only does work on maps. It combines the label and data
1677 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001678
Laurence Lundblade59289e52019-12-30 13:44:37 -08001679 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1680 tags into bit flags associated with the data item. No actual decoding
1681 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001682
Laurence Lundblade59289e52019-12-30 13:44:37 -08001683 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301684 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301685 string allocater to create contiguous space for the item. It
1686 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001687
Laurence Lundblade59289e52019-12-30 13:44:37 -08001688 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1689 atomic data item has a "major type", an integer "argument" and optionally
1690 some content. For text and byte strings, the content is the bytes
1691 that make up the string. These are the smallest data items that are
1692 considered to be well-formed. The content may also be other data items in
1693 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001694
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001695 Roughly this takes 300 bytes of stack for vars. Need to
1696 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001697
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301698 */
1699
1700
1701/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001702 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001703 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001704int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1705 const QCBORItem *pItem,
1706 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001707{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001708 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
1709 if(pItem->uTags[i] == 0xffff) {
1710 break;
1711 }
1712 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1713 return 1;
1714 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001715 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001716
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001717 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001718}
1719
1720
1721/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001722 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001723 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001724QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001725{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001726 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001727
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001728 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001729 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001730 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1731 goto Done;
1732 }
1733
1734 // Error out if not all the bytes are consumed
1735 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1736 nReturn = QCBOR_ERR_EXTRA_BYTES;
1737 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001738
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001739Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301740 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001741 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001742 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001743
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001744 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001745}
1746
1747
1748
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001749/*
1750
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001751Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001752
Laurence Lundbladeee851742020-01-08 08:37:05 -08001753 - Hit end of input before it was expected while decoding type and
1754 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001755
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001756 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001757
Laurence Lundbladeee851742020-01-08 08:37:05 -08001758 - Hit end of input while decoding a text or byte string
1759 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001760
Laurence Lundbladeee851742020-01-08 08:37:05 -08001761 - Encountered conflicting tags -- e.g., an item is tagged both a date
1762 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001763
Laurence Lundbladeee851742020-01-08 08:37:05 -08001764 - Encontered an array or mapp that has too many items
1765 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001766
Laurence Lundbladeee851742020-01-08 08:37:05 -08001767 - Encountered array/map nesting that is too deep
1768 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001769
Laurence Lundbladeee851742020-01-08 08:37:05 -08001770 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1771 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001772
Laurence Lundbladeee851742020-01-08 08:37:05 -08001773 - The type of a map label is not a string or int
1774 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001775
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001776 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001777
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001778 */
1779
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001780
1781
Laurence Lundbladef6531662018-12-04 10:42:22 +09001782
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001783/* ===========================================================================
1784 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001785
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001786 This implements a simple sting allocator for indefinite length
1787 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1788 implements the function type QCBORStringAllocate and allows easy
1789 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001790
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001791 This particular allocator is built-in for convenience. The caller
1792 can implement their own. All of this following code will get
1793 dead-stripped if QCBORDecode_SetMemPool() is not called.
1794
1795 This is a very primitive memory allocator. It does not track
1796 individual allocations, only a high-water mark. A free or
1797 reallocation must be of the last chunk allocated.
1798
1799 The size of the pool and offset to free memory are packed into the
1800 first 8 bytes of the memory pool so we don't have to keep them in
1801 the decode context. Since the address of the pool may not be
1802 aligned, they have to be packed and unpacked as if they were
1803 serialized data of the wire or such.
1804
1805 The sizes packed in are uint32_t to be the same on all CPU types
1806 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001807 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001808
1809
Laurence Lundbladeee851742020-01-08 08:37:05 -08001810static inline int
1811MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001812{
1813 // Use of UsefulInputBuf is overkill, but it is convenient.
1814 UsefulInputBuf UIB;
1815
Laurence Lundbladeee851742020-01-08 08:37:05 -08001816 // Just assume the size here. It was checked during SetUp so
1817 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001818 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1819 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1820 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1821 return UsefulInputBuf_GetError(&UIB);
1822}
1823
1824
Laurence Lundbladeee851742020-01-08 08:37:05 -08001825static inline int
1826MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001827{
1828 // Use of UsefulOutBuf is overkill, but convenient. The
1829 // length check performed here is useful.
1830 UsefulOutBuf UOB;
1831
1832 UsefulOutBuf_Init(&UOB, Pool);
1833 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1834 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1835 return UsefulOutBuf_GetError(&UOB);
1836}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001837
1838
1839/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001840 Internal function for an allocation, reallocation free and destuct.
1841
1842 Having only one function rather than one each per mode saves space in
1843 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001844
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001845 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1846 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001847static UsefulBuf
1848MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001849{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001850 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001851
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001852 uint32_t uPoolSize;
1853 uint32_t uFreeOffset;
1854
1855 if(uNewSize > UINT32_MAX) {
1856 // This allocator is only good up to 4GB. This check should
1857 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1858 goto Done;
1859 }
1860 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1861
1862 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1863 goto Done;
1864 }
1865
1866 if(uNewSize) {
1867 if(pMem) {
1868 // REALLOCATION MODE
1869 // Calculate pointer to the end of the memory pool. It is
1870 // assumed that pPool + uPoolSize won't wrap around by
1871 // assuming the caller won't pass a pool buffer in that is
1872 // not in legitimate memory space.
1873 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1874
1875 // Check that the pointer for reallocation is in the range of the
1876 // pool. This also makes sure that pointer math further down
1877 // doesn't wrap under or over.
1878 if(pMem >= pPool && pMem < pPoolEnd) {
1879 // Offset to start of chunk for reallocation. This won't
1880 // wrap under because of check that pMem >= pPool. Cast
1881 // is safe because the pool is always less than UINT32_MAX
1882 // because of check in QCBORDecode_SetMemPool().
1883 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1884
1885 // Check to see if the allocation will fit. uPoolSize -
1886 // uMemOffset will not wrap under because of check that
1887 // pMem is in the range of the uPoolSize by check above.
1888 if(uNewSize <= uPoolSize - uMemOffset) {
1889 ReturnValue.ptr = pMem;
1890 ReturnValue.len = uNewSize;
1891
1892 // Addition won't wrap around over because uNewSize was
1893 // checked to be sure it is less than the pool size.
1894 uFreeOffset = uMemOffset + uNewSize32;
1895 }
1896 }
1897 } else {
1898 // ALLOCATION MODE
1899 // uPoolSize - uFreeOffset will not underflow because this
1900 // pool implementation makes sure uFreeOffset is always
1901 // smaller than uPoolSize through this check here and
1902 // reallocation case.
1903 if(uNewSize <= uPoolSize - uFreeOffset) {
1904 ReturnValue.len = uNewSize;
1905 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001906 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001907 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001908 }
1909 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001910 if(pMem) {
1911 // FREE MODE
1912 // Cast is safe because of limit on pool size in
1913 // QCBORDecode_SetMemPool()
1914 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1915 } else {
1916 // DESTRUCT MODE
1917 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001918 }
1919 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001920
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001921 UsefulBuf Pool = {pPool, uPoolSize};
1922 MemPool_Pack(Pool, uFreeOffset);
1923
1924Done:
1925 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001926}
1927
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001928
Laurence Lundbladef6531662018-12-04 10:42:22 +09001929/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001930 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001931 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001932QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1933 UsefulBuf Pool,
1934 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001935{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001936 // The pool size and free mem offset are packed into the beginning
1937 // of the pool memory. This compile time check make sure the
1938 // constant in the header is correct. This check should optimize
1939 // down to nothing.
1940 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001941 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001942 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001943
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001944 // The pool size and free offset packed in to the beginning of pool
1945 // memory are only 32-bits. This check will optimize out on 32-bit
1946 // machines.
1947 if(Pool.len > UINT32_MAX) {
1948 return QCBOR_ERR_BUFFER_TOO_LARGE;
1949 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001950
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001951 // This checks that the pool buffer given is big enough.
1952 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1953 return QCBOR_ERR_BUFFER_TOO_SMALL;
1954 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001955
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001956 pMe->StringAllocator.pfAllocator = MemPool_Function;
1957 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1958 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001959
Laurence Lundblade30816f22018-11-10 13:40:22 +07001960 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001961}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001962
Laurence Lundblade1341c592020-04-11 14:19:05 -07001963#include <stdio.h>
1964void printdecode(QCBORDecodeContext *pMe, const char *szName)
1965{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001966 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1967 szName,
1968 (uint32_t)pMe->InBuf.cursor,
1969 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001970 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001971 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1972 break;
1973 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001974 printf("%2s %2d %5d %s %6u %2d %d\n",
1975 pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001976 i,
1977 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001978 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1979 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1980 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001981 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001982 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1983 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001984 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001985
Laurence Lundblade1341c592020-04-11 14:19:05 -07001986 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001987 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07001988}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001989
1990
1991/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001992 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001993 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001994static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001995ConsumeItem(QCBORDecodeContext *pMe,
1996 const QCBORItem *pItemToConsume,
1997 uint_fast8_t *puNextNestLevel)
1998{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001999 QCBORError nReturn;
2000 QCBORItem Item;
2001
2002 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002003
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002004 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002005 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002006
Laurence Lundblade1341c592020-04-11 14:19:05 -07002007 /* This works for definite and indefinite length
2008 * maps and arrays by using the nesting level
2009 */
2010 do {
2011 nReturn = QCBORDecode_GetNext(pMe, &Item);
2012 if(nReturn != QCBOR_SUCCESS) {
2013 goto Done;
2014 }
2015 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002016
Laurence Lundblade1341c592020-04-11 14:19:05 -07002017 if(puNextNestLevel != NULL) {
2018 *puNextNestLevel = Item.uNextNestLevel;
2019 }
2020 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002021
Laurence Lundblade1341c592020-04-11 14:19:05 -07002022 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002023 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002024 if(puNextNestLevel != NULL) {
2025 /* Just pass the nesting level through */
2026 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2027 }
2028 nReturn = QCBOR_SUCCESS;
2029 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002030
2031Done:
2032 return nReturn;
2033}
2034
2035
Laurence Lundblade1341c592020-04-11 14:19:05 -07002036/* Return true if the labels in Item1 and Item2 are the same.
2037 Works only for integer and string labels. Returns false
2038 for any other type. */
2039static inline bool
2040MatchLabel(QCBORItem Item1, QCBORItem Item2)
2041{
2042 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2043 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2044 return true;
2045 }
2046 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002047 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002048 return true;
2049 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002050 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002051 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2052 return true;
2053 }
2054 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2055 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2056 return true;
2057 }
2058 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002059
Laurence Lundblade1341c592020-04-11 14:19:05 -07002060 /* Other label types are never matched */
2061 return false;
2062}
2063
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002064static inline bool
2065MatchType(QCBORItem Item1, QCBORItem Item2)
2066{
2067 if(Item1.uDataType == Item2.uDataType) {
2068 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002069 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002070 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002071 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002072 return true;
2073 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002074 return false;
2075}
2076
2077
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002078/**
2079 \brief Search a map for a set of items
2080
2081 @param[in] pMe The decode context to search.
2082 @param[in,out] pItemArray The items to search for and the items found.
2083 @param[in] pCBContext Context for the not-found item call back
2084 @param[in] pfCallback Function to call on items not matched in pItemArray
2085
2086 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2087
2088 @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.
2089
2090 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2091
2092 @retval Also errors returned by QCBORDecode_GetNext().
2093
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002094 On input pItemArray contains a list of labels and data types
2095 of items to be found.
2096
2097 On output the fully retrieved items are filled in with
2098 values and such. The label was matched, so it never changes.
2099
2100 If an item was not found, its data type is set to none.
2101
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002102 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002103static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002104MapSearch(QCBORDecodeContext *pMe,
2105 QCBORItem *pItemArray,
2106 size_t *puOffset,
2107 size_t *puEndOffset,
2108 void *pCBContext,
2109 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002110{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002111 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002112
2113 // TODO: what if pre-order cursor is not at the same level as map? This should be OK.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002114 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
2115 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002116 }
2117
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002118 QCBORDecodeNesting SaveNesting;
2119 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002120
2121 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2122
2123 /* Loop over all the items in the map. They could be
2124 * deeply nested and this should handle both definite
2125 * and indefinite length maps and arrays, so this
2126 * adds some complexity. */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002127 const uint8_t uMapNestLevel = DecodeNesting_GetMapModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002128
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002129 uint_fast8_t uNextNestLevel;
2130
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002131 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002132
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002133 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002134 do {
2135 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002136 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002137
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002138 /* Get the item */
2139 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002140 uReturn = QCBORDecode_GetNext(pMe, &Item);
2141 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002142 /* Got non-well-formed CBOR */
2143 goto Done;
2144 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002145
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002146 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002147 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002148 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002149 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002150 if(MatchLabel(Item, *pIterator)) {
2151 // A label match has been found
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002152 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2153 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002154 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002155 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002156 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002157 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002158 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002159 goto Done;
2160 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002161
2162 /* Successful match. Return the item. */
2163 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002164 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002165 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002166 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002167 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002168 } else {
2169 /* Call the call back on unmatched labels */
2170 /* It is tempting to do duplicate detection here, but that would
2171 require dynamic memory allocation because the number of labels
2172 that might be encountered is unbounded.
2173 */
2174 if(pfCallback) {
2175 uReturn = (*pfCallback)(pCBContext, &Item);
2176 if(uReturn != QCBOR_SUCCESS) {
2177 goto Done;
2178 }
2179 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002180 }
2181 }
2182
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002183 /* Consume the item whether matched or not. This
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002184 does the work of traversing maps and array and
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002185 everything in them. In this loop only the
2186 items at the current nesting level are examined
2187 to match the labels. */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002188 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2189 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002190 goto Done;
2191 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002192
2193 } while (uNextNestLevel >= uMapNestLevel);
2194
2195
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002196 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002197
2198 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2199 // Cast OK because encoded CBOR is limited to UINT32_MAX
2200 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2201 // TODO: is zero *puOffset OK?
2202 if(puEndOffset) {
2203 *puEndOffset = uEndOffset;
2204 }
2205
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002206 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002207 int i;
2208 QCBORItem *pIterator;
2209 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002210 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002211 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002212 }
2213 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002214
2215Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002216 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002217
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002218 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002219}
2220
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002221
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002222
2223
Laurence Lundblade34691b92020-05-18 22:25:25 -07002224void QCBORDecode_ExitMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002225{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002226 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002227
Laurence Lundblade34691b92020-05-18 22:25:25 -07002228 (void)uType; // TODO: error check
2229
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002230/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002231 if(pMe->uMapEndOffset) {
2232 uEndOffset = pMe->uMapEndOffset;
2233 // It is only valid once.
2234 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002235 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002236 QCBORItem Dummy;
2237
2238 Dummy.uLabelType = QCBOR_TYPE_NONE;
2239
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002240 QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002241
2242 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002243// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002244
2245 printdecode(pMe, "start exit");
2246 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2247
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002248 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002249 printdecode(pMe, "end exit");
2250
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002251}
2252
2253
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002254void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe, UsefulBufC *pBstr)
2255{
2256 QCBORItem Item;
2257 QCBORDecode_GetNext(pMe, &Item);
2258 // Need to set UIB cursor to start of bstr and UIB length to end of bstr
2259
2260}
2261
2262//void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pCtx, int64_t uLabel, UsefulBufC *pBstr);
2263
2264//void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, UsefulBufC *pBstr);
2265
2266void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pCtx)
2267{
2268 // Need to set the cursor to end of the bstr and length to the next length
2269 // above in the nesting tree (or the top level length).
2270
2271}
2272
2273
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002274void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2275 int64_t nLabel,
2276 uint8_t uQcborType,
2277 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002278{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002279 if(pMe->uLastError != QCBOR_SUCCESS) {
2280 return;
2281 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002282
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002283 QCBORItem OneItemSeach[2];
2284 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2285 OneItemSeach[0].label.int64 = nLabel;
2286 OneItemSeach[0].uDataType = uQcborType;
2287 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002288
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002289 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002290 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002291 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002292 }
2293
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002294 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2295 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002296 }
2297
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002298 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002299}
2300
2301
Laurence Lundbladeda095972020-06-06 18:35:33 -07002302void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2303 const char *szLabel,
2304 uint8_t uQcborType,
2305 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002306{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002307 if(pMe->uLastError != QCBOR_SUCCESS) {
2308 return;
2309 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002310
Laurence Lundbladed02ea8e2020-06-06 18:38:19 -07002311
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002312 QCBORItem OneItemSeach[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002314 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2315 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2316 OneItemSeach[0].uDataType = uQcborType;
2317 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002318
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002319 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002320 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002321 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002322 }
2323
Laurence Lundbladeda095972020-06-06 18:35:33 -07002324
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002325 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002326 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327 }
2328
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002329 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002330}
2331
2332
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002333static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002334{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002335 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2336 /* Must match the tag */
2337 if(uDataType == TagSpec.uTaggedType) {
2338 return QCBOR_SUCCESS;
2339 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002340 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002341 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2342 /* Must check all the possible types for the tag content */
2343 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002344 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2345 return QCBOR_SUCCESS;
2346 }
2347 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002348 /* Didn't match any of the tag content types */
2349 /* Check the tag for the either case */
2350 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2351 if(uDataType == TagSpec.uTaggedType) {
2352 return QCBOR_SUCCESS;
2353 }
2354 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002355 }
2356
2357 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002358}
2359
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002360
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002361void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2362 int64_t nLabel,
2363 TagSpecification TagSpec,
2364 QCBORItem *pItem)
2365{
2366 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2367 if(pMe->uLastError != QCBOR_SUCCESS) {
2368 return;
2369 }
2370
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002371 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002372}
2373
2374void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2375 const char *szLabel,
2376 TagSpecification TagSpec,
2377 QCBORItem *pItem)
2378{
2379 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2380 if(pMe->uLastError != QCBOR_SUCCESS) {
2381 return;
2382 }
2383
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002384 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002385}
2386
2387void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2388 int64_t nLabel,
2389 TagSpecification TagSpec,
2390 UsefulBufC *pString)
2391{
2392 QCBORItem Item;
2393 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2394 if(pMe->uLastError == QCBOR_SUCCESS) {
2395 *pString = Item.val.string;
2396 }
2397}
2398
2399void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2400 const char * szLabel,
2401 TagSpecification TagSpec,
2402 UsefulBufC *pString)
2403{
2404 QCBORItem Item;
2405 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2406 if(pMe->uLastError == QCBOR_SUCCESS) {
2407 *pString = Item.val.string;
2408 }
2409}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002410
Laurence Lundblade1341c592020-04-11 14:19:05 -07002411
Laurence Lundblade34691b92020-05-18 22:25:25 -07002412static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002413{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002414 if(pMe->uLastError != QCBOR_SUCCESS) {
2415 // Already in error state; do nothing.
2416 return;
2417 }
2418
2419 size_t uOffset;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002420 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002421 if(pMe->uLastError != QCBOR_SUCCESS) {
2422 return;
2423 }
2424
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002425 /* Need to get the current pre-order nesting level and cursor to be
2426 at the first item in the map/array just entered.
2427
2428 Also need to current map nesting level and start cursor to
2429 be at the right place.
2430
2431 The UsefulInBuf offset could be anywhere, so no assumption is
2432 made about it.
2433
2434 No assumption is made about the pre-order nesting level either.
2435
2436 However the map mode nesting level is assumed to be one above
2437 the map level that is being entered.
2438 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002439 /* Seek to the data item that is the map or array */
2440 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002441 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002442
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002443 // TODO: check error?
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002444 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002445
Laurence Lundblade34691b92020-05-18 22:25:25 -07002446 printdecode(pMe, "FinishEnter");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002447}
2448
2449
Laurence Lundblade34691b92020-05-18 22:25:25 -07002450void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002451{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002452 QCBORItem OneItemSeach[2];
2453 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2454 OneItemSeach[0].label.int64 = nLabel;
2455 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2456 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002457
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002458 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002459 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002460}
2461
2462
Laurence Lundblade34691b92020-05-18 22:25:25 -07002463void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002465 QCBORItem OneItemSeach[2];
2466 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2467 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2468 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2469 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002470
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002471 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002472}
2473
2474
Laurence Lundblade34691b92020-05-18 22:25:25 -07002475void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002477 QCBORItem OneItemSeach[2];
2478 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2479 OneItemSeach[0].label.int64 = nLabel;
2480 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2481 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002482
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002483 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002484}
2485
2486
2487void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2488{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002489 QCBORItem OneItemSeach[2];
2490 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2491 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2492 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2493 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002494
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002495 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002496}
2497
2498
2499
2500
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002501
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002503void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002504{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002505 if(pMe->uLastError != QCBOR_SUCCESS) {
2506 // Already in error state; do nothing.
2507 return;
2508 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509
2510 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002511 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002512 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002513 if(pMe->uLastError != QCBOR_SUCCESS) {
2514 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002515 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002516 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002517 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2518 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002519 }
2520
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002521 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002522
Laurence Lundblade34691b92020-05-18 22:25:25 -07002523 printdecode(pMe, "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524}
2525
2526
2527
2528QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2529{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002530 return MapSearch(pCtx, pItemList, NULL, NULL, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002531}
2532
2533
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002534QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx, QCBORItem *pItemList, void *pCallbackCtx, QCBORItemCallback pfCB)
2535{
2536 return MapSearch(pCtx, pItemList, NULL, NULL, pCallbackCtx, pfCB);
2537}
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002538
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002539
2540
Laurence Lundblade1341c592020-04-11 14:19:05 -07002541void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002542{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002543 // TODO: check for map mode; test this
Laurence Lundblade1341c592020-04-11 14:19:05 -07002544 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2545 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2546}
2547
2548
Laurence Lundblade1341c592020-04-11 14:19:05 -07002549
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002550void QCBORDecode_EnterBstr(QCBORDecodeContext *pMe)
2551{
2552 if(pMe->uLastError != QCBOR_SUCCESS) {
2553 // Already in error state; do nothing.
2554 return;
2555 }
2556
2557 /* Get the data item that is the map that is being searched */
2558 QCBORItem Item;
2559 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2560 if(pMe->uLastError != QCBOR_SUCCESS) {
2561 return;
2562 }
2563 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
2564 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2565 return;
2566 }
2567
2568 // TODO: check for tag 24
2569
2570 // Need to move UIB input cursor to the right place
2571
2572 // Really this is a subtraction and an assignment; not much code
2573 // There is a range check in the seek.
2574 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2575
2576 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset - Item.val.string.len);
2577
2578 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOffset);
2579
2580 // TODO: comment on cast
2581 pMe->uLastError = (uint8_t)DecodeNesting_Descend2(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING, UINT16_MAX, (uint32_t)uEndOffset);
2582}
2583
2584
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002585
Laurence Lundbladee6430642020-03-14 21:15:44 -07002586
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002587
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002588
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002589
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002590
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002591
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002592static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
2593{
2594 switch(pItem->uDataType) {
2595 case QCBOR_TYPE_TRUE:
2596 *pBool = true;
2597 return QCBOR_SUCCESS;
2598 break;
2599
2600 case QCBOR_TYPE_FALSE:
2601 *pBool = false;
2602 return QCBOR_SUCCESS;
2603 break;
2604
2605 default:
2606 return QCBOR_ERR_UNEXPECTED_TYPE;
2607 break;
2608 }
2609}
Laurence Lundbladee6430642020-03-14 21:15:44 -07002610
Laurence Lundbladec4537442020-04-14 18:53:22 -07002611void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002612{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002613 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002614 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002615 return;
2616 }
2617
Laurence Lundbladec4537442020-04-14 18:53:22 -07002618 QCBORError nError;
2619 QCBORItem Item;
2620
2621 nError = QCBORDecode_GetNext(pMe, &Item);
2622 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002623 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002624 return;
2625 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002626 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002627}
2628
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002629void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002630{
2631 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002632 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002633
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002634 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002635}
2636
2637
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002638void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
2639{
2640 QCBORItem Item;
2641 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2642
2643 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
2644}
2645
2646
2647
2648void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002649{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002650 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002651 // Already in error state, do nothing
2652 return;
2653 }
2654
2655 QCBORError nError;
2656 QCBORItem Item;
2657
2658 nError = QCBORDecode_GetNext(pMe, &Item);
2659 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002660 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002661 return;
2662 }
2663
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002664 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
2665
2666 if(pMe->uLastError == QCBOR_SUCCESS) {
2667 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002668 }
2669}
2670
Laurence Lundbladec4537442020-04-14 18:53:22 -07002671
2672
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002673
2674static QCBORError ConvertBigNum(const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002675{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002676 *pbIsNegative = false;
2677
2678 bool bMustBeTagged = true; // TODO: fix this
2679
2680 switch(pItem->uDataType) {
2681 case QCBOR_TYPE_BYTE_STRING:
2682 // TODO: check that there is no tag here?
2683 if(bMustBeTagged) {
2684 return QCBOR_ERR_UNEXPECTED_TYPE;
2685 } else {
2686 *pValue = pItem->val.string;
2687 return QCBOR_SUCCESS;
2688 }
2689 break;
2690
2691 case QCBOR_TYPE_POSBIGNUM:
2692 *pValue = pItem->val.string;
2693 return QCBOR_SUCCESS;
2694 break;
2695
2696 case QCBOR_TYPE_NEGBIGNUM:
2697 *pbIsNegative = true;
2698 *pValue = pItem->val.string;
2699 return QCBOR_SUCCESS;
2700 break;
2701
2702 default:
2703 return QCBOR_ERR_UNEXPECTED_TYPE;
2704 break;
2705 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002706}
2707
2708
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002709/**
2710 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
2711 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
2712 will always be false on the asumption that it is positive, but it can be interpretted as
2713 negative if the the sign is know from other context.
2714 @param[out] pValue The bytes that make up the big num
2715 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
2716
2717 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
2718 a positive big num or a negative big num.
2719
2720 */
2721void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
2722{
2723 if(pMe->uLastError != QCBOR_SUCCESS) {
2724 // Already in error state, do nothing
2725 return;
2726 }
2727
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002728 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002729 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
2730 if(uError != QCBOR_SUCCESS) {
2731 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002732 return;
2733 }
2734
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002735 pMe->uLastError = (uint8_t)ConvertBigNum(&Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002736}
2737
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002738void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002739{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002740 QCBORItem Item;
2741 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002742
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002743 pMe->uLastError = (uint8_t)ConvertBigNum(&Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07002744}
2745
Laurence Lundbladec4537442020-04-14 18:53:22 -07002746
2747
2748
Laurence Lundbladee6430642020-03-14 21:15:44 -07002749
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002750typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002751
2752
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002753// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002754static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002755{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002756 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002757
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002758 if(uResult != 0) {
2759 /* This loop will run a maximum of 19 times because
2760 * UINT64_MAX < 10 ^^ 19. More than that will cause
2761 * exit with the overflow error
2762 */
2763 for(; nExponent > 0; nExponent--) {
2764 if(uResult > UINT64_MAX / 10) {
2765 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
2766 }
2767 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002768 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002769
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002770 for(; nExponent < 0; nExponent++) {
2771 uResult = uResult / 10;
2772 if(uResult == 0) {
2773 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2774 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002775 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002776 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002777 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002778
2779 *puResult = uResult;
2780
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002781 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002782}
2783
2784
Laurence Lundbladee6430642020-03-14 21:15:44 -07002785/* Convert a decimal fraction to an int64_t without using
2786 floating point or math libraries. Most decimal fractions
2787 will not fit in an int64_t and this will error out with
2788 under or overflow
2789 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002790static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002791{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002792 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002793
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002794 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002795
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002796 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002797 * INT64_MAX < 2^31. More than that will cause
2798 * exist with the overflow error
2799 */
2800 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002801 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002802 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002803 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002804 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002805 nExponent--;
2806 }
2807
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002808 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002809 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002810 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2811 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002812 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002813 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002814 }
2815
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002816 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002817
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002818 return QCBOR_SUCCESS;
2819}
2820
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002821/*
2822 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
2823 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002824static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2825{
2826 uint64_t uResult;
2827
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002828 // Take the absolute value of the mantissa and convert to unsigned.
2829 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002830 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2831
2832 // Do the exponentiation of the positive mantissa
2833 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2834 if(uReturn) {
2835 return uReturn;
2836 }
2837
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002838
Laurence Lundblade983500d2020-05-14 11:49:34 -07002839 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2840 of INT64_MIN. This assumes two's compliment representation where
2841 INT64_MIN is one increment farther from 0 than INT64_MAX.
2842 Trying to write -INT64_MIN doesn't work to get this because the
2843 compiler tries to work with an int64_t which can't represent
2844 -INT64_MIN.
2845 */
2846 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
2847
2848 // Error out if too large
2849 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002850 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2851 }
2852
2853 // Casts are safe because of checks above
2854 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2855
2856 return QCBOR_SUCCESS;
2857}
2858
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002859/*
2860 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
2861 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002862static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2863{
2864 if(nMantissa < 0) {
2865 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2866 }
2867
2868 // Cast to unsigned is OK because of check for negative
2869 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2870 // Exponentiation is straight forward
2871 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2872}
2873
2874
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002875#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002876
2877
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002878static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002879{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002880 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002881
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002882 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002883 const uint8_t *pByte = BigNum.ptr;
2884 size_t uLen = BigNum.len;
2885 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07002886 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002887 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002888 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07002889 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002890 }
2891
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002892 *pResult = uResult;
2893 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002894}
2895
Laurence Lundblade887add82020-05-17 05:50:34 -07002896static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002897{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002898 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002899}
2900
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002901static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002902{
2903 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002904 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
2905 if(uError) {
2906 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002907 }
2908 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2909 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002910 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002911}
2912
2913
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002914static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002915{
2916 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07002917 /* negaative int furthest from zero is INT64_MIN
2918 which is expressed as -INT64_MAX-1. The value of
2919 a negative bignum is -n-1, one further from zero
2920 than the positive bignum */
2921
2922 /* say INT64_MIN is -2; then INT64_MAX is 1.
2923 Then -n-1 <= INT64_MIN.
2924 Then -n -1 <= -INT64_MAX - 1
2925 THen n <= INT64_MAX. */
2926 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002927 if(uError) {
2928 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002929 }
2930 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07002931 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07002932 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07002933 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002934 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002935}
2936
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002937#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07002938
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002939
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002940/*
2941Convert a integers and floats to an int64_t.
2942
2943\param[in] uOptions Bit mask list of conversion options.
2944
2945\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
2946
2947\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
2948
2949\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
2950
2951*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002952static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
2953{
2954 switch(pItem->uDataType) {
2955 // TODO: float when ifdefs are set
2956 case QCBOR_TYPE_DOUBLE:
2957 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
2958 // TODO: what about under/overflow here?
2959 // Invokes the floating-point HW and/or compiler-added libraries
2960 feclearexcept(FE_ALL_EXCEPT);
2961 *pnValue = llround(pItem->val.dfnum);
2962 if(fetestexcept(FE_INVALID)) {
2963 // TODO: better error code
2964 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2965 }
2966 } else {
2967 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2968 }
2969 break;
2970
2971 case QCBOR_TYPE_INT64:
2972 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
2973 *pnValue = pItem->val.int64;
2974 } else {
2975 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2976 }
2977 break;
2978
2979 case QCBOR_TYPE_UINT64:
2980 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
2981 if(pItem->val.uint64 < INT64_MAX) {
2982 *pnValue = pItem->val.int64;
2983 } else {
2984 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2985 }
2986 } else {
2987 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2988 }
2989 break;
2990
2991 default:
2992 return QCBOR_ERR_UNEXPECTED_TYPE;
2993 }
2994 return QCBOR_SUCCESS;
2995}
2996
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002997
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002998void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
2999 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003000 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003001 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003002{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003003 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003004 return;
3005 }
3006
Laurence Lundbladee6430642020-03-14 21:15:44 -07003007 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003008 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3009 if(uError) {
3010 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003011 return;
3012 }
3013
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003014 if(pItem) {
3015 *pItem = Item;
3016 }
3017
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003018 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003019}
3020
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003021
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003022void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3023 int64_t nLabel,
3024 uint32_t uOptions,
3025 int64_t *pnValue,
3026 QCBORItem *pItem)
3027{
3028 QCBORItem Item;
3029 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3030
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003031 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003032}
3033
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003034
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003035void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3036 const char * szLabel,
3037 uint32_t uOptions,
3038 int64_t *pnValue,
3039 QCBORItem *pItem)
3040{
3041 if(pMe->uLastError != QCBOR_SUCCESS) {
3042 return;
3043 }
3044
3045 QCBORItem Item;
3046 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3047
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003048 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003049}
3050
3051
3052
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003053/*
3054 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003055
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003056 \param[in] uOptions Bit mask list of conversion options.
3057
3058 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3059
3060 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3061
3062 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3063
3064 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003065static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3066{
3067 QCBORError uErr;
3068
3069 switch(pItem->uDataType) {
3070
3071 case QCBOR_TYPE_POSBIGNUM:
3072 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3073 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003074 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003075 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003076 }
3077 break;
3078
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003079 case QCBOR_TYPE_NEGBIGNUM:
3080 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3081 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003082 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003083 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003084 }
3085 break;
3086
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003087#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3088 case QCBOR_TYPE_DECIMAL_FRACTION:
3089 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3090 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3091 pItem->val.expAndMantissa.nExponent,
3092 pnValue,
3093 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003094 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003095 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3096 }
3097 break;
3098
3099 case QCBOR_TYPE_BIGFLOAT:
3100 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3101 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3102 pItem->val.expAndMantissa.nExponent,
3103 pnValue,
3104 Exponentitate2);
3105 } else {
3106 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3107 }
3108 break;
3109
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003110 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3111 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3112 int64_t nMantissa;
3113 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3114 if(uErr) {
3115 return uErr;
3116 }
3117 return ExponentiateNN(nMantissa,
3118 pItem->val.expAndMantissa.nExponent,
3119 pnValue,
3120 Exponentitate10);
3121 } else {
3122 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3123 }
3124 break;
3125
3126 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3127 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3128 int64_t nMantissa;
3129 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3130 if(uErr) {
3131 return uErr;
3132 }
3133 return ExponentiateNN(nMantissa,
3134 pItem->val.expAndMantissa.nExponent,
3135 pnValue,
3136 Exponentitate10);
3137 } else {
3138 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3139 }
3140 break;
3141
3142 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3143 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3144 int64_t nMantissa;
3145 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3146 if(uErr) {
3147 return uErr;
3148 }
3149 return ExponentiateNN(nMantissa,
3150 pItem->val.expAndMantissa.nExponent,
3151 pnValue,
3152 Exponentitate2);
3153 } else {
3154 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3155 }
3156 break;
3157
3158 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3159 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3160 int64_t nMantissa;
3161 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3162 if(uErr) {
3163 return uErr;
3164 }
3165 return ExponentiateNN(nMantissa,
3166 pItem->val.expAndMantissa.nExponent,
3167 pnValue,
3168 Exponentitate2);
3169 } else {
3170 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003171 }
3172 break;
3173
Laurence Lundbladec4537442020-04-14 18:53:22 -07003174 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003175 return QCBOR_ERR_UNEXPECTED_TYPE;
3176#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003177 }
3178}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003179
3180
Laurence Lundbladec4537442020-04-14 18:53:22 -07003181/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003182 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003183 */
3184void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003185{
3186 QCBORItem Item;
3187
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003188 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003189
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003190 if(pMe->uLastError == QCBOR_SUCCESS) {
3191 // The above conversion succeeded
3192 return;
3193 }
3194
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003195 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003196 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003197 return;
3198 }
3199
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003200 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003201}
3202
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003203
3204/*
3205Public function, see header qcbor/qcbor_decode.h file
3206*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003207void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3208{
3209 QCBORItem Item;
3210
3211 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3212
3213 if(pMe->uLastError == QCBOR_SUCCESS) {
3214 // The above conversion succeeded
3215 return;
3216 }
3217
3218 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3219 // The above conversion failed in a way that code below can't correct
3220 return;
3221 }
3222
3223 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3224}
3225
3226
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003227/*
3228Public function, see header qcbor/qcbor_decode.h file
3229*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003230void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3231{
3232 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003233 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3234
3235 if(pMe->uLastError == QCBOR_SUCCESS) {
3236 // The above conversion succeeded
3237 return;
3238 }
3239
3240 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3241 // The above conversion failed in a way that code below can't correct
3242 return;
3243 }
3244
3245 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3246}
3247
3248
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003249static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3250{
3251 switch(pItem->uDataType) {
3252 // TODO: type flaot
3253 case QCBOR_TYPE_DOUBLE:
3254 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3255 feclearexcept(FE_ALL_EXCEPT);
3256 double dRounded = round(pItem->val.dfnum);
3257 // TODO: over/underflow
3258 if(fetestexcept(FE_INVALID)) {
3259 // TODO: better error code
3260 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3261 } else if(isnan(dRounded)) {
3262 // TODO: better error code
3263 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3264 } else if(dRounded >= 0) {
3265 *puValue = (uint64_t)dRounded;
3266 } else {
3267 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3268 }
3269 } else {
3270 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3271 }
3272 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003273
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003274 case QCBOR_TYPE_INT64:
3275 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3276 if(pItem->val.int64 >= 0) {
3277 *puValue = (uint64_t)pItem->val.int64;
3278 } else {
3279 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3280 }
3281 } else {
3282 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3283 }
3284 break;
3285
3286 case QCBOR_TYPE_UINT64:
3287 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3288 *puValue = pItem->val.uint64;
3289 } else {
3290 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3291 }
3292 break;
3293
3294 default:
3295 return QCBOR_ERR_UNEXPECTED_TYPE;
3296 }
3297 return QCBOR_SUCCESS;
3298}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003299
3300
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003301void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3302 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003303 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003304 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003305{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003306 if(pMe->uLastError != QCBOR_SUCCESS) {
3307 return;
3308 }
3309
Laurence Lundbladec4537442020-04-14 18:53:22 -07003310 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003311
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003312 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3313 if(uError) {
3314 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 return;
3316 }
3317
Laurence Lundbladea826c502020-05-10 21:07:00 -07003318 if(pItem) {
3319 *pItem = Item;
3320 }
3321
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003322 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003323}
3324
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003325
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003326void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3327 int64_t nLabel,
3328 uint32_t uOptions,
3329 uint64_t *puValue,
3330 QCBORItem *pItem)
3331{
3332 QCBORItem Item;
3333 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3334
3335 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3336}
3337
3338
3339void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3340 const char * szLabel,
3341 uint32_t uOptions,
3342 uint64_t *puValue,
3343 QCBORItem *pItem)
3344{
3345 if(pMe->uLastError != QCBOR_SUCCESS) {
3346 return;
3347 }
3348
3349 QCBORItem Item;
3350 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3351
3352 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3353}
3354
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003355/*
3356 Public function, see header qcbor/qcbor_decode.h file
3357*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003358static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3359{
3360 QCBORError uErr;
3361
3362 switch(pItem->uDataType) {
3363
3364 case QCBOR_TYPE_POSBIGNUM:
3365 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3366 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3367 } else {
3368 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3369 }
3370 break;
3371
3372 case QCBOR_TYPE_NEGBIGNUM:
3373 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3374 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3375 } else {
3376 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3377 }
3378 break;
3379
3380#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3381
3382 case QCBOR_TYPE_DECIMAL_FRACTION:
3383 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3384 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3385 pItem->val.expAndMantissa.nExponent,
3386 puValue,
3387 Exponentitate10);
3388 } else {
3389 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3390 }
3391 break;
3392
3393 case QCBOR_TYPE_BIGFLOAT:
3394 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3395 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3396 pItem->val.expAndMantissa.nExponent,
3397 puValue,
3398 Exponentitate2);
3399 } else {
3400 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3401 }
3402 break;
3403
3404 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3405 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3406 // TODO: Would be better to convert to unsigned
3407 int64_t nMantissa;
3408 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3409 if(uErr != QCBOR_SUCCESS) {
3410 return uErr;
3411 }
3412 return ExponentitateNU(nMantissa,
3413 pItem->val.expAndMantissa.nExponent,
3414 puValue,
3415 Exponentitate10);
3416 } else {
3417 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3418 }
3419 break;
3420
3421 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3422 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3423 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3424 } else {
3425 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3426 }
3427 break;
3428
3429 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3430 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3431 // TODO: Would be better to convert to unsigned
3432 int64_t nMantissa;
3433 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3434 if(uErr != QCBOR_SUCCESS) {
3435 return uErr;
3436 }
3437 return ExponentitateNU(nMantissa,
3438 pItem->val.expAndMantissa.nExponent,
3439 puValue,
3440 Exponentitate2);
3441 } else {
3442 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3443 }
3444 break;
3445
3446 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3447 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3448 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3449 } else {
3450 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3451 }
3452 break;
3453#endif
3454 default:
3455 return QCBOR_ERR_UNEXPECTED_TYPE;
3456 }
3457}
3458
3459
3460void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003461{
3462 QCBORItem Item;
3463
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003464 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003465
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003466 if(pMe->uLastError == QCBOR_SUCCESS) {
3467 // The above conversion succeeded
3468 return;
3469 }
3470
3471 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3472 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473 return;
3474 }
3475
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003476 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477}
3478
Laurence Lundbladec4537442020-04-14 18:53:22 -07003479
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003480/*
3481Public function, see header qcbor/qcbor_decode.h file
3482*/
3483void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3484{
3485 QCBORItem Item;
3486
3487 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3488
3489 if(pMe->uLastError == QCBOR_SUCCESS) {
3490 // The above conversion succeeded
3491 return;
3492 }
3493
3494 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3495 // The above conversion failed in a way that code below can't correct
3496 return;
3497 }
3498
3499 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3500}
3501
3502
3503/*
3504Public function, see header qcbor/qcbor_decode.h file
3505*/
3506void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
3507{
3508 QCBORItem Item;
3509 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
3510
3511 if(pMe->uLastError == QCBOR_SUCCESS) {
3512 // The above conversion succeeded
3513 return;
3514 }
3515
3516 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3517 // The above conversion failed in a way that code below can't correct
3518 return;
3519 }
3520
3521 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3522}
3523
3524
3525static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
3526{
3527 switch(pItem->uDataType) {
3528 // TODO: float when ifdefs are set
3529 case QCBOR_TYPE_DOUBLE:
3530 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3531 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3532 *pdValue = pItem->val.dfnum;
3533 } else {
3534 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3535 }
3536 }
3537 break;
3538
3539 case QCBOR_TYPE_INT64:
3540 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3541 // TODO: how does this work?
3542 *pdValue = (double)pItem->val.int64;
3543
3544 } else {
3545 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3546 }
3547 break;
3548
3549 case QCBOR_TYPE_UINT64:
3550 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3551 *pdValue = (double)pItem->val.uint64;
3552 } else {
3553 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3554 }
3555 break;
3556
3557 default:
3558 return QCBOR_ERR_UNEXPECTED_TYPE;
3559 }
3560
3561 return QCBOR_SUCCESS;
3562}
3563
3564
3565
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003566void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
3567 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003568 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003569 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003570{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003571 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003572 return;
3573 }
3574
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003575 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003576
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003577 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003578 if(uError) {
3579 pMe->uLastError = (uint8_t)uError;
3580 return;
3581 }
3582
3583 if(pItem) {
3584 *pItem = Item;
3585 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003586
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003587 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003588}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003589
Laurence Lundbladec4537442020-04-14 18:53:22 -07003590
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003591void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
3592 int64_t nLabel,
3593 uint32_t uOptions,
3594 double *pdValue,
3595 QCBORItem *pItem)
3596{
3597 QCBORItem Item;
3598 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3599
3600 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
3601}
3602
3603void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3604 const char * szLabel,
3605 uint32_t uOptions,
3606 double *pdValue,
3607 QCBORItem *pItem)
3608{
3609 if(pMe->uLastError != QCBOR_SUCCESS) {
3610 return;
3611 }
3612
3613 QCBORItem Item;
3614 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3615
3616 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
3617}
3618
3619
3620
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003621static double ConvertBigNumToDouble(const UsefulBufC BigNum)
3622{
3623 double dResult;
3624
3625 dResult = 0.0;
3626 const uint8_t *pByte = BigNum.ptr;
3627 size_t uLen = BigNum.len;
3628 /* This will overflow and become the float value INFINITY if the number
3629 is too large to fit. No error will be logged.
3630 TODO: should an error be logged? */
3631 while(uLen--) {
3632 dResult = (dResult * 256.0) + (double)*pByte++;
3633 }
3634
3635 return dResult;
3636}
3637
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003638static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003639{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003640 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003641 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
3642
3643 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003644 switch(pItem->uDataType) {
3645 // TODO: type float
3646 case QCBOR_TYPE_DECIMAL_FRACTION:
3647 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3648 // TODO: rounding and overflow errors
3649 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
3650 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
3651 } else {
3652 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3653 }
3654 break;
3655
3656 case QCBOR_TYPE_BIGFLOAT:
3657 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
3658 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
3659 exp2((double)pItem->val.expAndMantissa.nExponent);
3660 } else {
3661 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3662 }
3663 break;
3664
3665 case QCBOR_TYPE_POSBIGNUM:
3666 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3667 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
3668 } else {
3669 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3670 }
3671 break;
3672
3673 case QCBOR_TYPE_NEGBIGNUM:
3674 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07003675 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003676 } else {
3677 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3678 }
3679 break;
3680
3681 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3682 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3683 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3684 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
3685 } else {
3686 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3687 }
3688 break;
3689
3690 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3691 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3692 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3693 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
3694 } else {
3695 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3696 }
3697 break;
3698
3699 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3700 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3701 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3702 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
3703 } else {
3704 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3705 }
3706 break;
3707
3708 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3709 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07003710 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003711 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
3712 } else {
3713 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3714 }
3715 break;
3716
3717 default:
3718 return QCBOR_ERR_UNEXPECTED_TYPE;
3719 }
3720
3721 return QCBOR_SUCCESS;
3722}
3723
3724
3725/*
3726 Public function, see header qcbor/qcbor_decode.h file
3727*/
3728void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
3729{
3730
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003731 QCBORItem Item;
3732
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003733 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003734
3735 if(pMe->uLastError == QCBOR_SUCCESS) {
3736 // The above conversion succeeded
3737 return;
3738 }
3739
3740 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3741 // The above conversion failed in a way that code below can't correct
3742 return;
3743 }
3744
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003745 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003746}
3747
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003748
3749/*
3750Public function, see header qcbor/qcbor_decode.h file
3751*/
3752void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
3753{
3754 QCBORItem Item;
3755
3756 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
3757
3758 if(pMe->uLastError == QCBOR_SUCCESS) {
3759 // The above conversion succeeded
3760 return;
3761 }
3762
3763 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3764 // The above conversion failed in a way that code below can't correct
3765 return;
3766 }
3767
3768 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
3769}
3770
3771
3772/*
3773Public function, see header qcbor/qcbor_decode.h file
3774*/
3775void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
3776{
3777 QCBORItem Item;
3778 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
3779
3780 if(pMe->uLastError == QCBOR_SUCCESS) {
3781 // The above conversion succeeded
3782 return;
3783 }
3784
3785 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3786 // The above conversion failed in a way that code below can't correct
3787 return;
3788 }
3789
3790 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
3791}