blob: dc5e626103f2a21b8b229b1c1b6c0616bdad5f57 [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 Lundblade9c905e82020-04-25 11:31:38 -0700124inline static bool
125DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700126{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
128 return true;
129 } else {
130 return false;
131 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132}
133
Laurence Lundblade937ea812020-05-08 11:38:23 -0700134// Determine if at the end of a map or array while in map mode
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700135inline static bool
136DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
137{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700138 if(pNesting->pCurrentMap && pNesting->pCurrentMap->uMapMode) {
139 if(pNesting->pCurrentMap->uCount == 0) {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700140 // TODO: won't work for indefinite length
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700141 // In map mode and consumed all items, so it is the end
142 return true;
143 } else {
144 // In map mode, all items not consumed, so it is NOT the end
145 return false;
146 }
147 } else {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700148 // Not in map mode. The end is determined in other ways.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700149 return false;
150 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700151}
152
153
Laurence Lundbladeee851742020-01-08 08:37:05 -0800154inline static int
155DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700156{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700157 return pNesting->pCurrent->uCount == UINT16_MAX;
158}
159
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700160inline static int
161DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
162{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700163 return (bool)pNesting->pCurrentMap->uMapMode;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700164}
165
Laurence Lundbladeee851742020-01-08 08:37:05 -0800166inline static uint8_t
167DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800168{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800169 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700170 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800171 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172}
173
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700174inline static uint8_t
175DecodeNesting_GetMapModeLevel(QCBORDecodeNesting *pNesting)
176{
177 // Check in DecodeNesting_Descend and never having
178 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
179 return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0]));
180}
181
Laurence Lundbladeee851742020-01-08 08:37:05 -0800182inline static int
183DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700185 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
190}
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800193inline static QCBORError
194DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700195{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800196 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700197 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800201 // breaks can only occur when the map/array is indefinite length
202 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
203 return QCBOR_ERR_BAD_BREAK;
204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800206 // if all OK, the break reduces the level of nesting
207 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800208
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800209 return QCBOR_SUCCESS;
210}
211
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700212// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700213/* Decrements the map/array counter if possible. If decrement
214 closed out a map or array, then level up in nesting and decrement
215 again, until, the top is reached or the end of a map mode is reached
216 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800217inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700218DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800219{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700220 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700221 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800222
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800223 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700224 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800225 pNesting->pCurrent->uCount--;
226 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700227
228 if(pNesting->pCurrent->uCount != 0) {
229 // Did not close out an array or map, so nothing further
230 break;
231 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700232
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700233 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700234 // In map mode the level-up must be done explicitly
235 break;
236 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700237
238 // Closed out an array or map so level up
239 pNesting->pCurrent--;
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700240 /*if(pNesting->pCurrent->uMapMode) {
241 // Bring the current map level along if new level is a map
242 // TODO: must search up until a mapmode level is found.
243 pNesting->pCurrentMap = pNesting->pCurrent;
244 } */
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700245
246 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 }
248}
249
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700250inline static void
251DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
252{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700253 pNesting->pCurrentMap = pNesting->pCurrent;
254 pNesting->pCurrentMap->uMapMode = 1;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700255 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700256 pNesting->pCurrentMap->uOffset = (uint32_t)uOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700257}
258
259inline static void
260DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
261{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700262 pNesting->pCurrentMap->uMapMode = 0;
263 pNesting->pCurrent = pNesting->pCurrentMap - 1; // TODO error check
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700264
265 DecodeNesting_DecrementCount(pNesting);
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700266
267 while(1) {
268 pNesting->pCurrentMap--;
269 if(pNesting->pCurrentMap->uMapMode) {
270 break;
271 }
272 if(pNesting->pCurrentMap == &(pNesting->pMapsAndArrays[0])) {
273 break;
274 }
275 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700276}
277
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800278// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800279inline static QCBORError
280DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700282 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800284 if(pItem->val.uCount == 0) {
285 // Nothing to do for empty definite lenth arrays. They are just are
286 // effectively the same as an item that is not a map or array
287 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530288 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800290
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800291 // Error out if arrays is too long to handle
292 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
294 goto Done;
295 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800296
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800297 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
299 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
300 goto Done;
301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800302
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800303 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700304 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800306 // Record a few details for this nesting level
307 pNesting->pCurrent->uMajorType = pItem->uDataType;
308 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700309 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700310 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700312Done:
313 return nReturn;;
314}
315
Laurence Lundbladeee851742020-01-08 08:37:05 -0800316inline static void
317DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318{
319 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
320}
321
322
323
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700324/*
325 This list of built-in tags. Only add tags here that are
326 clearly established and useful. Once a tag is added here
327 it can't be taken out as that would break backwards compatibility.
328 There are only 48 slots available forever.
329 */
330static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800331 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
332 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
333 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
334 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
335 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
336 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700337 CBOR_TAG_COSE_ENCRYPTO,
338 CBOR_TAG_COSE_MAC0,
339 CBOR_TAG_COSE_SIGN1,
340 CBOR_TAG_ENC_AS_B64URL,
341 CBOR_TAG_ENC_AS_B64,
342 CBOR_TAG_ENC_AS_B16,
343 CBOR_TAG_CBOR,
344 CBOR_TAG_URI,
345 CBOR_TAG_B64URL,
346 CBOR_TAG_B64,
347 CBOR_TAG_REGEX,
348 CBOR_TAG_MIME,
349 CBOR_TAG_BIN_UUID,
350 CBOR_TAG_CWT,
351 CBOR_TAG_ENCRYPT,
352 CBOR_TAG_MAC,
353 CBOR_TAG_SIGN,
354 CBOR_TAG_GEO_COORD,
355 CBOR_TAG_CBOR_MAGIC
356};
357
358// This is used in a bit of cleverness in GetNext_TaggedItem() to
359// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800360// these types. This will break if the first six items in
361// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
362// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
363#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
364#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
365#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
366#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
367#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
368#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700369
Laurence Lundblade59289e52019-12-30 13:44:37 -0800370#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
371 QCBOR_TAGFLAG_DATE_EPOCH |\
372 QCBOR_TAGFLAG_POS_BIGNUM |\
373 QCBOR_TAGFLAG_NEG_BIGNUM |\
374 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
375 QCBOR_TAGFLAG_BIGFLOAT)
376
377#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
378 QCBOR_TAGFLAG_DATE_EPOCH |\
379 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700380 QCBOR_TAGFLAG_NEG_BIGNUM)
381
382#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
383#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
384#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
385
386static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
387{
388 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800389 /*
390 This is a cross-check to make sure the above array doesn't
391 accidentally get made too big. In normal conditions the above
392 test should optimize out as all the values are known at compile
393 time.
394 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700395 return -1;
396 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800397
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700398 if(uTag > UINT16_MAX) {
399 // This tag map works only on 16-bit tags
400 return -1;
401 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800402
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700403 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
404 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
405 return nTagBitIndex;
406 }
407 }
408 return -1; // Indicates no match
409}
410
411static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
412{
413 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
414 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
415 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
416 }
417 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800418
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700419 return -1; // Indicates no match
420}
421
422/*
423 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800424
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700425 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800426 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700427 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428static QCBORError
429TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
430 uint64_t uTag,
431 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700432{
433 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
434 if(nTagBitIndex >= 0) {
435 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
436 *puTagBitIndex = (uint8_t)nTagBitIndex;
437 return QCBOR_SUCCESS;
438 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700440 if(pCallerConfiguredTagMap) {
441 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
442 return QCBOR_ERR_TOO_MANY_TAGS;
443 }
444 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
445 if(nTagBitIndex >= 0) {
446 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
447
448 *puTagBitIndex = (uint8_t)nTagBitIndex;
449 return QCBOR_SUCCESS;
450 }
451 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800452
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700453 return QCBOR_ERR_BAD_OPT_TAG;
454}
455
456
457
Laurence Lundbladeee851742020-01-08 08:37:05 -0800458/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
460
461 The following four functions are pretty wrappers for invocation of
462 the string allocator supplied by the caller.
463
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800465
Laurence Lundbladeee851742020-01-08 08:37:05 -0800466static inline void
467StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800468{
469 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
470}
471
Laurence Lundbladeee851742020-01-08 08:37:05 -0800472// StringAllocator_Reallocate called with pMem NULL is
473// equal to StringAllocator_Allocate()
474static inline UsefulBuf
475StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
476 void *pMem,
477 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800478{
479 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
480}
481
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482static inline UsefulBuf
483StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800484{
485 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
486}
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488static inline void
489StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800490{
491 if(pMe->pfAllocator) {
492 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
493 }
494}
495
496
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498/*===========================================================================
499 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700500
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800501 See qcbor/qcbor_decode.h for definition of the object
502 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800503 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700504/*
505 Public function, see header file
506 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800507void QCBORDecode_Init(QCBORDecodeContext *me,
508 UsefulBufC EncodedCBOR,
509 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700510{
511 memset(me, 0, sizeof(QCBORDecodeContext));
512 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513 // Don't bother with error check on decode mode. If a bad value is
514 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700515 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700516 DecodeNesting_Init(&(me->nesting));
517}
518
519
520/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700521 Public function, see header file
522 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800523void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
524 QCBORStringAllocate pfAllocateFunction,
525 void *pAllocateContext,
526 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700527{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800528 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
529 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
530 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700531}
532
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800533
534/*
535 Public function, see header file
536 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
538 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700539{
540 me->pCallerConfiguredTagList = pTagList;
541}
542
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700543
544/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545 This decodes the fundamental part of a CBOR data item, the type and
546 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800547
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700548 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800549
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550 This does the network->host byte order conversion. The conversion
551 here also results in the conversion for floats in addition to that
552 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800553
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700554 This returns:
555 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800557 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800558 tags and floats and length for strings and arrays
559
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800560 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800562
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800563 The int type is preferred to uint8_t for some variables as this
564 avoids integer promotions, can reduce code size and makes
565 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700566 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800567inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
568 int *pnMajorType,
569 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800570 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700572 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800575 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800576
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700577 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800578 const int nTmpMajorType = nInitialByte >> 5;
579 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800580
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800581 // Where the number or argument accumulates
582 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800583
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800584 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800585 // Need to get 1,2,4 or 8 additional argument bytes Map
586 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800587 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800589 // Loop getting all the bytes in the argument
590 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800591 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800592 // This shift and add gives the endian conversion
593 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
594 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800596 // The reserved and thus-far unused additional info values
597 nReturn = QCBOR_ERR_UNSUPPORTED;
598 goto Done;
599 } else {
600 // Less than 24, additional info is argument or 31, an indefinite length
601 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800604
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700605 if(UsefulInputBuf_GetError(pUInBuf)) {
606 nReturn = QCBOR_ERR_HIT_END;
607 goto Done;
608 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // All successful if we got here.
611 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800612 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800613 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800615
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616Done:
617 return nReturn;
618}
619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800622 CBOR doesn't explicitly specify two's compliment for integers but all
623 CPUs use it these days and the test vectors in the RFC are so. All
624 integers in the CBOR structure are positive and the major type
625 indicates positive or negative. CBOR can express positive integers
626 up to 2^x - 1 where x is the number of bits and negative integers
627 down to 2^x. Note that negative numbers can be one more away from
628 zero than positive. Stdint, as far as I can tell, uses two's
629 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800632 used carefully here, and in particular why it isn't used in the interface.
633 Also see
634 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
635
636 Int is used for values that need less than 16-bits and would be subject
637 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800639inline static QCBORError
640DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700642 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
645 if (uNumber <= INT64_MAX) {
646 pDecodedItem->val.int64 = (int64_t)uNumber;
647 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800648
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 } else {
650 pDecodedItem->val.uint64 = uNumber;
651 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800652
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 }
654 } else {
655 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 // CBOR's representation of negative numbers lines up with the
657 // two-compliment representation. A negative integer has one
658 // more in range than a positive integer. INT64_MIN is
659 // equal to (-INT64_MAX) - 1.
660 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700661 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800662
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663 } else {
664 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000665 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 nReturn = QCBOR_ERR_INT_OVERFLOW;
667 }
668 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670 return nReturn;
671}
672
673// Make sure #define value line up as DecodeSimple counts on this.
674#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
675#error QCBOR_TYPE_FALSE macro value wrong
676#endif
677
678#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
679#error QCBOR_TYPE_TRUE macro value wrong
680#endif
681
682#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
683#error QCBOR_TYPE_NULL macro value wrong
684#endif
685
686#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
687#error QCBOR_TYPE_UNDEF macro value wrong
688#endif
689
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700690#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
691#error QCBOR_TYPE_BREAK macro value wrong
692#endif
693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
695#error QCBOR_TYPE_DOUBLE macro value wrong
696#endif
697
698#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
699#error QCBOR_TYPE_FLOAT macro value wrong
700#endif
701
702/*
703 Decode true, false, floats, break...
704 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800705inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800706DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700707{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700708 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeee851742020-01-08 08:37:05 -0800710 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 // above make sure uAdditionalInfo values line up with uDataType values.
712 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
713 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800715 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800716 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
717 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800718
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700719 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700720 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
721 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700722 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700723 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700724 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
725 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700726 break;
727 case DOUBLE_PREC_FLOAT:
728 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700729 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700730 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 case CBOR_SIMPLEV_FALSE: // 20
733 case CBOR_SIMPLEV_TRUE: // 21
734 case CBOR_SIMPLEV_NULL: // 22
735 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700736 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739 case CBOR_SIMPLEV_ONEBYTE: // 24
740 if(uNumber <= CBOR_SIMPLE_BREAK) {
741 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700742 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 goto Done;
744 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800745 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800747
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748 default: // 0-19
749 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800750 /*
751 DecodeTypeAndNumber will make uNumber equal to
752 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
753 safe because the 2, 4 and 8 byte lengths of uNumber are in
754 the double/float cases above
755 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756 pDecodedItem->val.uSimple = (uint8_t)uNumber;
757 break;
758 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800759
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760Done:
761 return nReturn;
762}
763
764
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700765/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530766 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800768inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
769 int nMajorType,
770 uint64_t uStrLen,
771 UsefulInputBuf *pUInBuf,
772 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700774 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
777 // This check makes the casts to size_t below safe.
778
779 // 4 bytes less than the largest sizeof() so this can be tested by
780 // putting a SIZE_MAX length in the CBOR test input (no one will
781 // care the limit on strings is 4 bytes shorter).
782 if(uStrLen > SIZE_MAX-4) {
783 nReturn = QCBOR_ERR_STRING_TOO_LONG;
784 goto Done;
785 }
786
787 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530788 if(UsefulBuf_IsNULLC(Bytes)) {
789 // Failed to get the bytes for this string item
790 nReturn = QCBOR_ERR_HIT_END;
791 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530793
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800794 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530795 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800796 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530797 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700798 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530799 goto Done;
800 }
801 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800802 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530803 } else {
804 // Normal case with no string allocator
805 pDecodedItem->val.string = Bytes;
806 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800807 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800808 // Cast because ternary operator causes promotion to integer
809 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
810 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530812Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700813 return nReturn;
814}
815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818
819
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700820
821
Laurence Lundbladeee851742020-01-08 08:37:05 -0800822// Make sure the constants align as this is assumed by
823// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700824#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
825#error QCBOR_TYPE_ARRAY value not lined up with major type
826#endif
827#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
828#error QCBOR_TYPE_MAP value not lined up with major type
829#endif
830
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800832 This gets a single data item and decodes it including preceding
833 optional tagging. This does not deal with arrays and maps and nesting
834 except to decode the data item introducing them. Arrays and maps are
835 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundbladeee851742020-01-08 08:37:05 -0800837 Errors detected here include: an array that is too long to decode,
838 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800840static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
841 QCBORItem *pDecodedItem,
842 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700844 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800845
Laurence Lundbladeee851742020-01-08 08:37:05 -0800846 /*
847 Get the major type and the number. Number could be length of more
848 bytes or the value depending on the major type nAdditionalInfo is
849 an encoding of the length of the uNumber and is needed to decode
850 floats and doubles
851 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800852 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800854 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700856 memset(pDecodedItem, 0, sizeof(QCBORItem));
857
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800858 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800859
Laurence Lundbladeee851742020-01-08 08:37:05 -0800860 // Error out here if we got into trouble on the type and number. The
861 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700862 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700864 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundbladeee851742020-01-08 08:37:05 -0800866 // At this point the major type and the value are valid. We've got
867 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
870 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800871 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700872 nReturn = QCBOR_ERR_BAD_INT;
873 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800874 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700875 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700876 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800877
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
879 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800880 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
881 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
882 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
883 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530884 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 }
888 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
891 case CBOR_MAJOR_TYPE_MAP: // Major type 5
892 // Record the number of items in the array or map
893 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
894 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
895 goto Done;
896 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800897 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530898 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800900 // type conversion OK because of check above
901 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800903 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800904 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
905 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800907
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700908 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800909 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700910 nReturn = QCBOR_ERR_BAD_INT;
911 } else {
912 pDecodedItem->val.uTagV = uNumber;
913 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
914 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917 case CBOR_MAJOR_TYPE_SIMPLE:
918 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800919 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800921
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 default:
923 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 nReturn = QCBOR_ERR_UNSUPPORTED;
925 break;
926 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928Done:
929 return nReturn;
930}
931
932
933
934/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800935 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800936 individual chunk items together into one QCBORItem using the string
937 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530939 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800941static inline QCBORError
942GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700943{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700944 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700945
946 // Get pointer to string allocator. First use is to pass it to
947 // GetNext_Item() when option is set to allocate for *every* string.
948 // Second use here is to allocate space to coallese indefinite
949 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800950 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
951 &(me->StringAllocator) :
952 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700954 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800955 nReturn = GetNext_Item(&(me->InBuf),
956 pDecodedItem,
957 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958 if(nReturn) {
959 goto Done;
960 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530963 // code in this function from here down can be eliminated. Run tests, except
964 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800965
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800966 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700967 const uint8_t uStringType = pDecodedItem->uDataType;
968 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 goto Done; // no need to do any work here on non-string types
970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800972 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530973 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800974 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530977 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800978 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
980 goto Done;
981 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700983 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700984 UsefulBufC FullString = NULLUsefulBufC;
985
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700987 // Get item for next chunk
988 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700989 // NULL string allocator passed here. Do not need to allocate
990 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800991 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700993 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800995
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530996 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700997 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800998 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301000 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 break;
1002 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001004 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301005 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001006 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 if(StringChunkItem.uDataType != uStringType ||
1008 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001009 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001010 break;
1011 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301013 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001014 // The first time throurgh FullString.ptr is NULL and this is
1015 // equivalent to StringAllocator_Allocate()
1016 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1017 UNCONST_POINTER(FullString.ptr),
1018 FullString.len + StringChunkItem.val.string.len);
1019
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301021 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001022 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
1024 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001026 // Copy new string chunk at the end of string so far.
1027 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001028 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001029
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001030 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1031 // Getting the item failed, clean up the allocated memory
1032 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001035Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 return nReturn;
1037}
1038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039
1040/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001041 Gets all optional tag data items preceding a data item that is not an
1042 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001043 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001044static QCBORError
1045GetNext_TaggedItem(QCBORDecodeContext *me,
1046 QCBORItem *pDecodedItem,
1047 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001048{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001049 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001050 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001051 uint64_t uTagBits = 0;
1052 if(pTags) {
1053 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001055
Laurence Lundblade59289e52019-12-30 13:44:37 -08001056 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001057 for(;;) {
1058 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001059 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001060 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001063 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1064 // Successful exit from loop; maybe got some tags, maybe not
1065 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001066 break;
1067 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001069 uint8_t uTagBitIndex;
1070 // Tag was mapped, tag was not mapped, error with tag list
1071 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001073 case QCBOR_SUCCESS:
1074 // Successfully mapped the tag
1075 uTagBits |= 0x01ULL << uTagBitIndex;
1076 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001077
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001078 case QCBOR_ERR_BAD_OPT_TAG:
1079 // Tag is not recognized. Do nothing
1080 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001082 default:
1083 // Error Condition
1084 goto Done;
1085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001087 if(pTags) {
1088 // Caller wants all tags recorded in the provided buffer
1089 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1090 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1091 goto Done;
1092 }
1093 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1094 pTags->uNumUsed++;
1095 }
1096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001098Done:
1099 return nReturn;
1100}
1101
1102
1103/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104 This layer takes care of map entries. It combines the label and data
1105 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001106 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001107static inline QCBORError
1108GetNext_MapEntry(QCBORDecodeContext *me,
1109 QCBORItem *pDecodedItem,
1110 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001111{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001112 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001113 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001114 if(nReturn)
1115 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001117 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001118 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001119 goto Done;
1120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001122 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1123 // In a map and caller wants maps decoded, not treated as arrays
1124
1125 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1126 // If in a map and the right decoding mode, get the label
1127
Laurence Lundbladeee851742020-01-08 08:37:05 -08001128 // Save label in pDecodedItem and get the next which will
1129 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001130 QCBORItem LabelItem = *pDecodedItem;
1131 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1132 if(nReturn)
1133 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301135 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001136
1137 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1138 // strings are always good labels
1139 pDecodedItem->label.string = LabelItem.val.string;
1140 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1141 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001142 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001143 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1144 goto Done;
1145 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1146 pDecodedItem->label.int64 = LabelItem.val.int64;
1147 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1148 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1149 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1150 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1151 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1152 pDecodedItem->label.string = LabelItem.val.string;
1153 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1154 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1155 } else {
1156 // label is not an int or a string. It is an arrray
1157 // or a float or such and this implementation doesn't handle that.
1158 // Also, tags on labels are ignored.
1159 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1160 goto Done;
1161 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001162 }
1163 } else {
1164 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001165 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1166 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1167 goto Done;
1168 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001169 // Decoding a map as an array
1170 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001171 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1172 // Cast is needed because of integer promotion
1173 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001174 }
1175 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001176
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001177Done:
1178 return nReturn;
1179}
1180
1181
1182/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001183 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001184 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001185 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001186QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1187 QCBORItem *pDecodedItem,
1188 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001190 // Stack ptr/int: 2, QCBORItem : 64
1191
Laurence Lundblade30816f22018-11-10 13:40:22 +07001192 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundblade937ea812020-05-08 11:38:23 -07001194 /* For a pre-order traversal a non-error end occurs when there
1195 are no more bytes to consume and the nesting level is at the top.
1196 If it's not at the top, then the CBOR is not well formed. This error
1197 is caught elsewhere.
1198
1199 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001200 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001201 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1202 goto Done;
1203 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001204
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001205 /* It is also an end of the input when in map mode and the cursor
Laurence Lundblade937ea812020-05-08 11:38:23 -07001206 is at the end of the map */
1207
1208
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001209 // This is to handle map and array mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001210 if(DecodeNesting_AtEnd(&(me->nesting))) {
1211// if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001212 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1213 goto Done;
1214 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001215
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001216 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001217 if(nReturn) {
1218 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001219 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301220
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001221 // Breaks ending arrays/maps are always processed at the end of this function.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301222 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301223 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301224 nReturn = QCBOR_ERR_BAD_BREAK;
1225 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301226 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001227
Laurence Lundblade6de37062018-10-15 12:22:42 +05301228 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301229 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301230 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001231
Laurence Lundblade6de37062018-10-15 12:22:42 +05301232 // Process the item just received for descent or decrement, and
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001233 // ascend if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001234 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001235 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001236 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001237 // Maps and arrays do count in as items in the map/array that encloses
1238 // them so a decrement needs to be done for them too, but that is done
1239 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001240 // are opened with the exception of an empty map or array.
1241 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001242 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001243 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001244 } else {
1245 // Decrement the count of items in the enclosing map/array
1246 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301247 // triggers a decrement in the map/array above that and
1248 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001249 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301251 if(nReturn) {
1252 goto Done;
1253 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001254
Laurence Lundblade6de37062018-10-15 12:22:42 +05301255 // For indefinite length maps/arrays, looking at any and
1256 // all breaks that might terminate them. The equivalent
1257 // for definite length maps/arrays happens in
1258 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001259 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301260 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1261 // Peek forward one item to see if it is a break.
1262 QCBORItem Peek;
1263 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1264 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1265 if(nReturn) {
1266 goto Done;
1267 }
1268 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1269 // It is not a break, rewind so it can be processed normally.
1270 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1271 break;
1272 }
1273 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301274 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301275 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1276 if(nReturn) {
1277 // break occured outside of an indefinite length array/map
1278 goto Done;
1279 }
1280 }
1281 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001282
Laurence Lundblade6de37062018-10-15 12:22:42 +05301283 // Tell the caller what level is next. This tells them what maps/arrays
1284 // were closed out and makes it possible for them to reconstruct
1285 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001286 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1287 // At end of a map / array in map mode, so next nest is 0 to
1288 // indicate this end.
1289 pDecodedItem->uNextNestLevel = 0;
1290 } else {
1291 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1292 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001293
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001294Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001295 if(nReturn != QCBOR_SUCCESS) {
1296 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1297 memset(pDecodedItem, 0, sizeof(QCBORItem));
1298 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001299 return nReturn;
1300}
1301
1302
Laurence Lundblade59289e52019-12-30 13:44:37 -08001303/*
1304 Mostly just assign the right data type for the date string.
1305 */
1306inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1307{
1308 // Stack Use: UsefulBuf 1 16
1309 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1310 return QCBOR_ERR_BAD_OPT_TAG;
1311 }
1312
1313 const UsefulBufC Temp = pDecodedItem->val.string;
1314 pDecodedItem->val.dateString = Temp;
1315 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1316 return QCBOR_SUCCESS;
1317}
1318
1319
1320/*
1321 Mostly just assign the right data type for the bignum.
1322 */
1323inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1324{
1325 // Stack Use: UsefulBuf 1 -- 16
1326 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1327 return QCBOR_ERR_BAD_OPT_TAG;
1328 }
1329 const UsefulBufC Temp = pDecodedItem->val.string;
1330 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001331 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001332 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1333 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001334 return QCBOR_SUCCESS;
1335}
1336
1337
1338/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001339 The epoch formatted date. Turns lots of different forms of encoding
1340 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001341 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001342static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001343{
1344 // Stack usage: 1
1345 QCBORError nReturn = QCBOR_SUCCESS;
1346
1347 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1348
1349 switch (pDecodedItem->uDataType) {
1350
1351 case QCBOR_TYPE_INT64:
1352 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1353 break;
1354
1355 case QCBOR_TYPE_UINT64:
1356 if(pDecodedItem->val.uint64 > INT64_MAX) {
1357 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1358 goto Done;
1359 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001360 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001361 break;
1362
1363 case QCBOR_TYPE_DOUBLE:
1364 {
1365 // This comparison needs to be done as a float before
1366 // conversion to an int64_t to be able to detect doubles
1367 // that are too large to fit into an int64_t. A double
1368 // has 52 bits of preceision. An int64_t has 63. Casting
1369 // INT64_MAX to a double actually causes a round up which
1370 // is bad and wrong for the comparison because it will
1371 // allow conversion of doubles that can't fit into a
1372 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1373 // the cutoff point as if that rounds up in conversion to
1374 // double it will still be less than INT64_MAX. 0x7ff is
1375 // picked because it has 11 bits set.
1376 //
1377 // INT64_MAX seconds is on the order of 10 billion years,
1378 // and the earth is less than 5 billion years old, so for
1379 // most uses this conversion error won't occur even though
1380 // doubles can go much larger.
1381 //
1382 // Without the 0x7ff there is a ~30 minute range of time
1383 // values 10 billion years in the past and in the future
1384 // where this this code would go wrong.
1385 const double d = pDecodedItem->val.dfnum;
1386 if(d > (double)(INT64_MAX - 0x7ff)) {
1387 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1388 goto Done;
1389 }
1390 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1391 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1392 }
1393 break;
1394
1395 default:
1396 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1397 goto Done;
1398 }
1399 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1400
1401Done:
1402 return nReturn;
1403}
1404
1405
1406#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1407/*
1408 Decode decimal fractions and big floats.
1409
1410 When called pDecodedItem must be the array that is tagged as a big
1411 float or decimal fraction, the array that has the two members, the
1412 exponent and mantissa.
1413
1414 This will fetch and decode the exponent and mantissa and put the
1415 result back into pDecodedItem.
1416 */
1417inline static QCBORError
1418QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1419{
1420 QCBORError nReturn;
1421
1422 // --- Make sure it is an array; track nesting level of members ---
1423 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1424 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1425 goto Done;
1426 }
1427
1428 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001429 // definite length arrays, but not for indefnite. Instead remember
1430 // the nesting level the two integers must be at, which is one
1431 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001432 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1433
1434 // --- Is it a decimal fraction or a bigfloat? ---
1435 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1436 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1437
1438 // --- Get the exponent ---
1439 QCBORItem exponentItem;
1440 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1441 if(nReturn != QCBOR_SUCCESS) {
1442 goto Done;
1443 }
1444 if(exponentItem.uNestingLevel != nNestLevel) {
1445 // Array is empty or a map/array encountered when expecting an int
1446 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1447 goto Done;
1448 }
1449 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1450 // Data arriving as an unsigned int < INT64_MAX has been converted
1451 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1452 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1453 // will be too large for this to handle and thus an error that will
1454 // get handled in the next else.
1455 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1456 } else {
1457 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1458 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1459 goto Done;
1460 }
1461
1462 // --- Get the mantissa ---
1463 QCBORItem mantissaItem;
1464 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1465 if(nReturn != QCBOR_SUCCESS) {
1466 goto Done;
1467 }
1468 if(mantissaItem.uNestingLevel != nNestLevel) {
1469 // Mantissa missing or map/array encountered when expecting number
1470 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1471 goto Done;
1472 }
1473 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1474 // Data arriving as an unsigned int < INT64_MAX has been converted
1475 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1476 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1477 // will be too large for this to handle and thus an error that
1478 // will get handled in an else below.
1479 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1480 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1481 // Got a good big num mantissa
1482 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1483 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001484 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1485 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1486 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001487 } else {
1488 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1489 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1490 goto Done;
1491 }
1492
1493 // --- Check that array only has the two numbers ---
1494 if(mantissaItem.uNextNestLevel == nNestLevel) {
1495 // Extra items in the decimal fraction / big num
1496 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1497 goto Done;
1498 }
1499
1500Done:
1501
1502 return nReturn;
1503}
1504#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1505
1506
1507/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001508 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001509 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001510QCBORError
1511QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1512 QCBORItem *pDecodedItem,
1513 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001514{
1515 QCBORError nReturn;
1516
1517 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1518 if(nReturn != QCBOR_SUCCESS) {
1519 goto Done;
1520 }
1521
1522#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1523#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1524#else
1525#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1526#endif
1527
1528 // Only pay attention to tags this code knows how to decode.
1529 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1530 case 0:
1531 // No tags at all or none we know about. Nothing to do.
1532 // This is the pass-through path of this function
1533 // that will mostly be taken when decoding any item.
1534 break;
1535
1536 case QCBOR_TAGFLAG_DATE_STRING:
1537 nReturn = DecodeDateString(pDecodedItem);
1538 break;
1539
1540 case QCBOR_TAGFLAG_DATE_EPOCH:
1541 nReturn = DecodeDateEpoch(pDecodedItem);
1542 break;
1543
1544 case QCBOR_TAGFLAG_POS_BIGNUM:
1545 case QCBOR_TAGFLAG_NEG_BIGNUM:
1546 nReturn = DecodeBigNum(pDecodedItem);
1547 break;
1548
1549#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1550 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1551 case QCBOR_TAGFLAG_BIGFLOAT:
1552 // For aggregate tagged types, what goes into pTags is only collected
1553 // from the surrounding data item, not the contents, so pTags is not
1554 // passed on here.
1555
1556 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1557 break;
1558#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1559
1560 default:
1561 // Encountering some mixed-up CBOR like something that
1562 // is tagged as both a string and integer date.
1563 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1564 }
1565
1566Done:
1567 if(nReturn != QCBOR_SUCCESS) {
1568 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1569 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1570 }
1571 return nReturn;
1572}
1573
1574
1575/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001576 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001577 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001578QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001579{
1580 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1581}
1582
1583
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001584/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301585 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301586 next one down. If a layer has no work to do for a particular item
1587 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001588
Laurence Lundblade59289e52019-12-30 13:44:37 -08001589 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1590 tagged data items, turning them into the local C representation.
1591 For the most simple it is just associating a QCBOR_TYPE with the data. For
1592 the complex ones that an aggregate of data items, there is some further
1593 decoding and a little bit of recursion.
1594
1595 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301596 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301597 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001598 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301600 - GetNext_MapEntry -- This handles the combining of two
1601 items, the label and the data, that make up a map entry.
1602 It only does work on maps. It combines the label and data
1603 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001604
Laurence Lundblade59289e52019-12-30 13:44:37 -08001605 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1606 tags into bit flags associated with the data item. No actual decoding
1607 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001608
Laurence Lundblade59289e52019-12-30 13:44:37 -08001609 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301610 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301611 string allocater to create contiguous space for the item. It
1612 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001613
Laurence Lundblade59289e52019-12-30 13:44:37 -08001614 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1615 atomic data item has a "major type", an integer "argument" and optionally
1616 some content. For text and byte strings, the content is the bytes
1617 that make up the string. These are the smallest data items that are
1618 considered to be well-formed. The content may also be other data items in
1619 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001620
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001621 Roughly this takes 300 bytes of stack for vars. Need to
1622 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001623
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301624 */
1625
1626
1627/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001628 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001629 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001630int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1631 const QCBORItem *pItem,
1632 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001633{
1634 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001635
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001636 uint8_t uTagBitIndex;
1637 // Do not care about errors in pCallerConfiguredTagMap here. They are
1638 // caught during GetNext() before this is called.
1639 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1640 return 0;
1641 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001642
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001643 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1644 return (uTagBit & pItem->uTagBits) != 0;
1645}
1646
1647
1648/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001649 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001650 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001651QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001652{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001653 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001654
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001655 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001656 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001657 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1658 goto Done;
1659 }
1660
1661 // Error out if not all the bytes are consumed
1662 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1663 nReturn = QCBOR_ERR_EXTRA_BYTES;
1664 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001665
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001666Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301667 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001668 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001669 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001670
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001671 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001672}
1673
1674
1675
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001676/*
1677
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001678Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001679
Laurence Lundbladeee851742020-01-08 08:37:05 -08001680 - Hit end of input before it was expected while decoding type and
1681 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001682
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001683 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001684
Laurence Lundbladeee851742020-01-08 08:37:05 -08001685 - Hit end of input while decoding a text or byte string
1686 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001687
Laurence Lundbladeee851742020-01-08 08:37:05 -08001688 - Encountered conflicting tags -- e.g., an item is tagged both a date
1689 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001690
Laurence Lundbladeee851742020-01-08 08:37:05 -08001691 - Encontered an array or mapp that has too many items
1692 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001693
Laurence Lundbladeee851742020-01-08 08:37:05 -08001694 - Encountered array/map nesting that is too deep
1695 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001696
Laurence Lundbladeee851742020-01-08 08:37:05 -08001697 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1698 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001699
Laurence Lundbladeee851742020-01-08 08:37:05 -08001700 - The type of a map label is not a string or int
1701 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001702
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001703 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001705 */
1706
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001707
1708
Laurence Lundbladef6531662018-12-04 10:42:22 +09001709
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001710/* ===========================================================================
1711 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001712
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001713 This implements a simple sting allocator for indefinite length
1714 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1715 implements the function type QCBORStringAllocate and allows easy
1716 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001717
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001718 This particular allocator is built-in for convenience. The caller
1719 can implement their own. All of this following code will get
1720 dead-stripped if QCBORDecode_SetMemPool() is not called.
1721
1722 This is a very primitive memory allocator. It does not track
1723 individual allocations, only a high-water mark. A free or
1724 reallocation must be of the last chunk allocated.
1725
1726 The size of the pool and offset to free memory are packed into the
1727 first 8 bytes of the memory pool so we don't have to keep them in
1728 the decode context. Since the address of the pool may not be
1729 aligned, they have to be packed and unpacked as if they were
1730 serialized data of the wire or such.
1731
1732 The sizes packed in are uint32_t to be the same on all CPU types
1733 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001734 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001735
1736
Laurence Lundbladeee851742020-01-08 08:37:05 -08001737static inline int
1738MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001739{
1740 // Use of UsefulInputBuf is overkill, but it is convenient.
1741 UsefulInputBuf UIB;
1742
Laurence Lundbladeee851742020-01-08 08:37:05 -08001743 // Just assume the size here. It was checked during SetUp so
1744 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001745 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1746 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1747 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1748 return UsefulInputBuf_GetError(&UIB);
1749}
1750
1751
Laurence Lundbladeee851742020-01-08 08:37:05 -08001752static inline int
1753MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001754{
1755 // Use of UsefulOutBuf is overkill, but convenient. The
1756 // length check performed here is useful.
1757 UsefulOutBuf UOB;
1758
1759 UsefulOutBuf_Init(&UOB, Pool);
1760 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1761 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1762 return UsefulOutBuf_GetError(&UOB);
1763}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001764
1765
1766/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001767 Internal function for an allocation, reallocation free and destuct.
1768
1769 Having only one function rather than one each per mode saves space in
1770 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001771
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001772 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1773 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001774static UsefulBuf
1775MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001776{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001777 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001778
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001779 uint32_t uPoolSize;
1780 uint32_t uFreeOffset;
1781
1782 if(uNewSize > UINT32_MAX) {
1783 // This allocator is only good up to 4GB. This check should
1784 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1785 goto Done;
1786 }
1787 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1788
1789 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1790 goto Done;
1791 }
1792
1793 if(uNewSize) {
1794 if(pMem) {
1795 // REALLOCATION MODE
1796 // Calculate pointer to the end of the memory pool. It is
1797 // assumed that pPool + uPoolSize won't wrap around by
1798 // assuming the caller won't pass a pool buffer in that is
1799 // not in legitimate memory space.
1800 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1801
1802 // Check that the pointer for reallocation is in the range of the
1803 // pool. This also makes sure that pointer math further down
1804 // doesn't wrap under or over.
1805 if(pMem >= pPool && pMem < pPoolEnd) {
1806 // Offset to start of chunk for reallocation. This won't
1807 // wrap under because of check that pMem >= pPool. Cast
1808 // is safe because the pool is always less than UINT32_MAX
1809 // because of check in QCBORDecode_SetMemPool().
1810 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1811
1812 // Check to see if the allocation will fit. uPoolSize -
1813 // uMemOffset will not wrap under because of check that
1814 // pMem is in the range of the uPoolSize by check above.
1815 if(uNewSize <= uPoolSize - uMemOffset) {
1816 ReturnValue.ptr = pMem;
1817 ReturnValue.len = uNewSize;
1818
1819 // Addition won't wrap around over because uNewSize was
1820 // checked to be sure it is less than the pool size.
1821 uFreeOffset = uMemOffset + uNewSize32;
1822 }
1823 }
1824 } else {
1825 // ALLOCATION MODE
1826 // uPoolSize - uFreeOffset will not underflow because this
1827 // pool implementation makes sure uFreeOffset is always
1828 // smaller than uPoolSize through this check here and
1829 // reallocation case.
1830 if(uNewSize <= uPoolSize - uFreeOffset) {
1831 ReturnValue.len = uNewSize;
1832 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001833 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001834 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001835 }
1836 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001837 if(pMem) {
1838 // FREE MODE
1839 // Cast is safe because of limit on pool size in
1840 // QCBORDecode_SetMemPool()
1841 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1842 } else {
1843 // DESTRUCT MODE
1844 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001845 }
1846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001847
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001848 UsefulBuf Pool = {pPool, uPoolSize};
1849 MemPool_Pack(Pool, uFreeOffset);
1850
1851Done:
1852 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001853}
1854
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001855
Laurence Lundbladef6531662018-12-04 10:42:22 +09001856/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001857 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001858 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001859QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1860 UsefulBuf Pool,
1861 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001862{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001863 // The pool size and free mem offset are packed into the beginning
1864 // of the pool memory. This compile time check make sure the
1865 // constant in the header is correct. This check should optimize
1866 // down to nothing.
1867 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001868 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001869 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001870
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001871 // The pool size and free offset packed in to the beginning of pool
1872 // memory are only 32-bits. This check will optimize out on 32-bit
1873 // machines.
1874 if(Pool.len > UINT32_MAX) {
1875 return QCBOR_ERR_BUFFER_TOO_LARGE;
1876 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001877
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001878 // This checks that the pool buffer given is big enough.
1879 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1880 return QCBOR_ERR_BUFFER_TOO_SMALL;
1881 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001882
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001883 pMe->StringAllocator.pfAllocator = MemPool_Function;
1884 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1885 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001886
Laurence Lundblade30816f22018-11-10 13:40:22 +07001887 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001888}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001889
Laurence Lundblade1341c592020-04-11 14:19:05 -07001890#include <stdio.h>
1891void printdecode(QCBORDecodeContext *pMe, const char *szName)
1892{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001893 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1894 szName,
1895 (uint32_t)pMe->InBuf.cursor,
1896 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001897 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001898 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1899 break;
1900 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001901 printf("%2s %2d %5d %s %6u %2d %d\n",
1902 pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001903 i,
1904 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001905 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1906 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1907 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001908 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001909 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1910 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001911 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001912
Laurence Lundblade1341c592020-04-11 14:19:05 -07001913 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001914 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07001915}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001916
1917
1918/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001919 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001920 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001921static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001922ConsumeItem(QCBORDecodeContext *pMe,
1923 const QCBORItem *pItemToConsume,
1924 uint_fast8_t *puNextNestLevel)
1925{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001926 QCBORError nReturn;
1927 QCBORItem Item;
1928
1929 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001930
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001931 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001932 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001933
Laurence Lundblade1341c592020-04-11 14:19:05 -07001934 /* This works for definite and indefinite length
1935 * maps and arrays by using the nesting level
1936 */
1937 do {
1938 nReturn = QCBORDecode_GetNext(pMe, &Item);
1939 if(nReturn != QCBOR_SUCCESS) {
1940 goto Done;
1941 }
1942 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001943
Laurence Lundblade1341c592020-04-11 14:19:05 -07001944 if(puNextNestLevel != NULL) {
1945 *puNextNestLevel = Item.uNextNestLevel;
1946 }
1947 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001948
Laurence Lundblade1341c592020-04-11 14:19:05 -07001949 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001950 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001951 if(puNextNestLevel != NULL) {
1952 /* Just pass the nesting level through */
1953 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1954 }
1955 nReturn = QCBOR_SUCCESS;
1956 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001957
1958Done:
1959 return nReturn;
1960}
1961
1962
Laurence Lundblade1341c592020-04-11 14:19:05 -07001963/* Return true if the labels in Item1 and Item2 are the same.
1964 Works only for integer and string labels. Returns false
1965 for any other type. */
1966static inline bool
1967MatchLabel(QCBORItem Item1, QCBORItem Item2)
1968{
1969 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1970 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1971 return true;
1972 }
1973 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001974 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001975 return true;
1976 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001977 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001978 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1979 return true;
1980 }
1981 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1982 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
1983 return true;
1984 }
1985 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001986
Laurence Lundblade1341c592020-04-11 14:19:05 -07001987 /* Other label types are never matched */
1988 return false;
1989}
1990
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001991static inline bool
1992MatchType(QCBORItem Item1, QCBORItem Item2)
1993{
1994 if(Item1.uDataType == Item2.uDataType) {
1995 return true;
1996 } else if(Item1.uLabelType == QCBOR_TYPE_ANY) {
1997 return true;
1998 } else if(Item2.uLabelType == QCBOR_TYPE_ANY) {
1999 return true;
2000 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002001 return false;
2002}
2003
2004
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002005/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002006 On input pItemArray contains a list of labels and data types
2007 of items to be found.
2008
2009 On output the fully retrieved items are filled in with
2010 values and such. The label was matched, so it never changes.
2011
2012 If an item was not found, its data type is set to none.
2013
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002014 */
2015QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002016GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002017{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002018 QCBORError nReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002019
2020 // 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 -07002021 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
2022 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002023 }
2024
Laurence Lundblade1341c592020-04-11 14:19:05 -07002025 QCBORDecodeNesting N = pMe->nesting;
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002026 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002027
2028 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2029 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2030 }
2031
2032 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2033
2034 /* Loop over all the items in the map. They could be
2035 * deeply nested and this should handle both definite
2036 * and indefinite length maps and arrays, so this
2037 * adds some complexity. */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002038 const uint8_t uMapNestLevel = DecodeNesting_GetMapModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002039
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002040 uint_fast8_t uNextNestLevel;
2041
2042 uint64_t uFound = 0;
2043
2044 do {
2045 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002046 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002047
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002048 /* Get the item */
2049 QCBORItem Item;
2050 nReturn = QCBORDecode_GetNext(pMe, &Item);
2051 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002052 /* Got non-well-formed CBOR */
2053 goto Done;
2054 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002055
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002056 /* See if item has one of the labels that are of interest */
2057 int i;
2058 QCBORItem *pIterator;
2059 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002060 if(MatchLabel(Item, *pIterator)) {
2061 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002062 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002063 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2064 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002065 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002066 if(!MatchType(Item, *pIterator)) {
2067 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2068 goto Done;
2069 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002070
2071 /* Successful match. Return the item. */
2072 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002073 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002074 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002075 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002076 }
2077 }
2078 }
2079
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002080 /* Consume the item whether matched or not. This
2081 does th work of traversing maps and array and
2082 everything in them. In this loop only the
2083 items at the current nesting level are examined
2084 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002085 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2086 if(nReturn) {
2087 goto Done;
2088 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002089
2090 } while (uNextNestLevel >= uMapNestLevel);
2091
2092
2093 nReturn = QCBOR_SUCCESS;
2094
2095 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2096 // Cast OK because encoded CBOR is limited to UINT32_MAX
2097 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2098 // TODO: is zero *puOffset OK?
2099 if(puEndOffset) {
2100 *puEndOffset = uEndOffset;
2101 }
2102
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002103 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002104 int i;
2105 QCBORItem *pIterator;
2106 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2107 if(!(uFound & (0x01ULL << i))) {
2108 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002109 }
2110 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002111
2112Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002113 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002114
Laurence Lundblade1341c592020-04-11 14:19:05 -07002115 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002116}
2117
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002118
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002119void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2120{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002121 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002122
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002123/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002124 if(pMe->uMapEndOffset) {
2125 uEndOffset = pMe->uMapEndOffset;
2126 // It is only valid once.
2127 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002128 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002129 QCBORItem Dummy;
2130
2131 Dummy.uLabelType = QCBOR_TYPE_NONE;
2132
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002133 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134
2135 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002136// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002137
2138 printdecode(pMe, "start exit");
2139 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2140
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002141 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002142 printdecode(pMe, "end exit");
2143
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002144}
2145
2146
2147QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002148 int64_t nLabel,
2149 uint8_t uQcborType,
2150 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002151{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002152 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002153
Laurence Lundblade1341c592020-04-11 14:19:05 -07002154 One[0].uLabelType = QCBOR_TYPE_INT64;
2155 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002156 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002157 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2158
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002159 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002160 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002161 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002162 }
2163
2164 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002165 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002166 }
2167
2168 *pItem = One[0];
2169
2170 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002171}
2172
2173
2174QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002175 const char *szLabel,
2176 uint8_t uQcborType,
2177 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002178{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002179 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002180
Laurence Lundblade1341c592020-04-11 14:19:05 -07002181 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2182 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002183 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002184 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2185
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002186 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002187 if(nReturn) {
2188 return nReturn;
2189 }
2190
2191 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002192 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002193 }
2194
2195 *pItem = One[0];
2196
2197 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002198}
2199
2200
Laurence Lundblade1341c592020-04-11 14:19:05 -07002201
Laurence Lundblade1341c592020-04-11 14:19:05 -07002202
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002203static int FinishEnter(QCBORDecodeContext *pMe, size_t uOffset)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002204{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002205 /* Seek to the data item that is the map or array */
2206 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002207 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002208
2209 /* Skip the data item that is the map or array */
2210 QCBORItem MapToEnter;
2211 // TODO: check error
2212 QCBORDecode_GetNext(pMe, &MapToEnter);
2213
2214 /* Enter map mode with an offset that is the first item
2215 in the map or array. */
2216 // TODO: what if map or array is empty?
2217 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
2218
2219
2220 printdecode(pMe, "Entered Map in Map");
2221
2222 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002223}
2224
2225
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002226QCBORError QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002227{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002228 /* Use GetItemsInMap to find the map by label, including the
2229 byte offset of it. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002230 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002231 One[0].uLabelType = QCBOR_TYPE_INT64;
2232 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002233 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002234 One[1].uLabelType = QCBOR_TYPE_NONE;
2235
2236 size_t uOffset;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002237 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002238 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002239 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002240 }
2241
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002242 /* The map to enter was found, now finish of entering it. */
2243 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002244
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002245 // TODO: error code?
Laurence Lundblade1341c592020-04-11 14:19:05 -07002246 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002247}
2248
2249
2250QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2251{
2252 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002253
Laurence Lundblade1341c592020-04-11 14:19:05 -07002254 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2255 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002256 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002257 One[1].uLabelType = QCBOR_TYPE_NONE;
2258
2259 size_t uOffset;
2260
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002261 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002262
2263 if(nReturn) {
2264 return nReturn;
2265 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002266
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002267 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002268
2269 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002270}
2271
2272
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002273QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002274{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002275 QCBORItem One[2];
2276
2277 One[0].uLabelType = QCBOR_TYPE_INT64;
2278 One[0].label.int64 = nLabel;
2279 One[0].uDataType = QCBOR_TYPE_ARRAY;
2280 One[1].uLabelType = QCBOR_TYPE_NONE;
2281
2282 size_t uOffset;
2283
2284 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
2285
2286 if(nReturn != QCBOR_SUCCESS) {
2287 return nReturn;
2288 }
2289
2290 FinishEnter(pMe, uOffset);
2291
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002292 return 0;
2293}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002294
Laurence Lundblade1341c592020-04-11 14:19:05 -07002295
2296QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2297{
2298 QCBORItem One[2];
2299
2300 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2301 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002302 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002303 One[1].uLabelType = QCBOR_TYPE_NONE;
2304
2305 size_t uOffset;
2306
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002307 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002308
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002309 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002310 return nReturn;
2311 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002312
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002313 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002314
2315 return 0;
2316}
2317
2318
2319
2320
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002321
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002322/* Next item must be map or this generates an error */
2323QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2324{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002325 QCBORItem Item;
2326 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327
2328 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002329 nReturn = QCBORDecode_GetNext(pMe, &Item);
2330 if(nReturn != QCBOR_SUCCESS) {
2331 return nReturn;
2332 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002333 if(Item.uDataType != QCBOR_TYPE_MAP) {
2334 return QCBOR_ERR_UNEXPECTED_TYPE;
2335 }
2336
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002337 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002338
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002339 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002340
Laurence Lundblade1341c592020-04-11 14:19:05 -07002341 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002342}
2343
2344
2345
2346QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2347{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002348 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002349}
2350
2351
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002352
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002353
2354
Laurence Lundblade1341c592020-04-11 14:19:05 -07002355void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002356{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002357 // TODO: check for map mode
2358 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2359 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2360}
2361
2362
2363QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2364{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002365 QCBORItem Item;
2366 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002367
2368 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002369 nReturn = QCBORDecode_GetNext(pMe, &Item);
2370 if(nReturn != QCBOR_SUCCESS) {
2371 return nReturn;
2372 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002373 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2374 return QCBOR_ERR_UNEXPECTED_TYPE;
2375 }
2376
2377 printdecode(pMe, "EnterArray");
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002378
2379 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002380
2381 return QCBOR_SUCCESS;
2382}
2383
2384
2385void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2386{
2387 // TODO: make sure we have entered an array
2388 // TODO: combine with code for map? It is the same so far.
2389 size_t uEndOffset;
2390
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002391 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002392 uEndOffset = pMe->uMapEndOffset;
2393 // It is only valid once.
2394 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002395 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002396 QCBORItem Dummy;
2397
2398 Dummy.uLabelType = QCBOR_TYPE_NONE;
2399
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002400 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002401
2402 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002403 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002404
Laurence Lundblade1341c592020-04-11 14:19:05 -07002405 printdecode(pMe, "start exit");
2406 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2407
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002408 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002409 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002410}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002411
Laurence Lundbladee6430642020-03-14 21:15:44 -07002412
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002413void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2414{
2415 // TODO: error handling
2416 QCBORItem Item;
2417 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2418 *pInt = Item.val.int64;
2419}
2420
2421void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2422{
2423 // TODO: error handling
2424 QCBORItem Item;
2425 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2426 *pBstr = Item.val.string;
2427}
2428
2429void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2430{
2431 // TODO: error handling
2432 QCBORItem Item;
2433 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2434 *pBstr = Item.val.string;
2435}
2436
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002437void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2438{
2439 // TODO: error handling
2440 QCBORItem Item;
2441 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_DATE_STRING, &Item);
2442 *pBstr = Item.val.string;
2443}
2444
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002445void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2446{
2447 // TODO: error handling
2448 QCBORItem Item;
2449 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2450 *pBstr = Item.val.string;
2451}
2452
Laurence Lundbladee6430642020-03-14 21:15:44 -07002453
Laurence Lundbladec4537442020-04-14 18:53:22 -07002454void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002455{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002456 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002457 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002458 return;
2459 }
2460
Laurence Lundbladec4537442020-04-14 18:53:22 -07002461 QCBORError nError;
2462 QCBORItem Item;
2463
2464 nError = QCBORDecode_GetNext(pMe, &Item);
2465 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002466 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002467 return;
2468 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002469
2470 switch(Item.uDataType) {
2471 case QCBOR_TYPE_TRUE:
2472 *pValue = true;
2473 break;
2474
2475 case QCBOR_TYPE_FALSE:
2476 *pValue = false;
2477 break;
2478
2479 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002480 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002481 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002482 }
2483}
2484
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002485#if 0
2486// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002487/* Types of text strings
2488 * Plain, b64, b64url, URI, regex, MIME Text
2489 * One function for each with options to expect plain?
2490 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002491 *
2492 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002493 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002494void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002495{
2496 QCBORItem Item;
2497 QCBORError nError;
2498
2499 nError = QCBORDecode_GetNext(pMe, &Item);
2500 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002501 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002502 return;
2503 }
2504
Laurence Lundbladec4537442020-04-14 18:53:22 -07002505 if(pLabel != NULL) {
2506 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002507 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002508 return;
2509 } else {
2510 // TODO: what about label allocation?
2511 pLabel->uLabelType = Item.uLabelType;
2512 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2513 }
2514 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002515
2516 switch(Item.uDataType) {
2517 case QCBOR_TYPE_TEXT_STRING:
2518 *pValue = Item.val.string;
2519 break;
2520
2521 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002522 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002523 }
2524}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002525#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002526
2527
Laurence Lundbladec4537442020-04-14 18:53:22 -07002528/*
2529 Options for MIME data, CBOR, positive big num, negative big num ??
2530 */
2531void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2532{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002533 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002534 // Already in error state, do nothing
2535 return;
2536 }
2537
2538 QCBORError nError;
2539 QCBORItem Item;
2540
2541 nError = QCBORDecode_GetNext(pMe, &Item);
2542 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002543 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002544 return;
2545 }
2546
2547 if(Item.uDataType == uType) {
2548 *pValue = Item.val.string;
2549 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002550 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002551 }
2552}
2553
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002554void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002555{
2556 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2557}
2558
2559
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002560void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002561{
2562 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2563}
2564
2565
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002566void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002567{
2568 // TODO: do these have to be tagged?
2569 // Probably should allow tagged or untagged, but not wrong-tagged
2570 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2571}
2572
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002573void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002574{
2575 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2576}
2577
2578
2579
Laurence Lundbladee6430642020-03-14 21:15:44 -07002580
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002581typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002582
2583
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002584// The main exponentiator that works on only positive numbers
2585static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002586{
2587 uint64_t uResult;
2588
2589 uResult = uMantissa;
2590
2591 /* This loop will run a maximum of 19 times because
2592 * UINT64_MAX < 10 ^^ 19. More than that will cause
2593 * exit with the overflow error
2594 */
2595 while(nExponent > 0) {
2596 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002597 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002598 }
2599 uResult = uResult * 10;
2600 nExponent--;
2601 }
2602
2603 while(nExponent < 0 ) {
2604 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002605 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002606 }
2607 uResult = uResult / 10;
2608 nExponent--;
2609 }
2610
2611 *puResult = uResult;
2612
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002613 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002614}
2615
2616
Laurence Lundbladee6430642020-03-14 21:15:44 -07002617/* Convert a decimal fraction to an int64_t without using
2618 floating point or math libraries. Most decimal fractions
2619 will not fit in an int64_t and this will error out with
2620 under or overflow
2621 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002622static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002623{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002624 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002625
2626 nResult = nMantissa;
2627
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002628 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002629 * INT64_MAX < 2^31. More than that will cause
2630 * exist with the overflow error
2631 */
2632 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002633 if(nResult > UINT64_MAX >> 1) {
2634 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002635 }
2636 nResult = nResult << 1;
2637 nExponent--;
2638 }
2639
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002640 while(nExponent < 0 ) {
2641 if(nResult == 0) {
2642 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2643 }
2644 nResult = nResult >> 1;
2645 nExponent--;
2646 }
2647
Laurence Lundbladee6430642020-03-14 21:15:44 -07002648 *pnResult = nResult;
2649
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002650 return QCBOR_SUCCESS;
2651}
2652
2653
2654static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2655{
2656 uint64_t uResult;
2657
2658 // Take the absolute value of the mantissa
2659 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2660
2661 // Do the exponentiation of the positive mantissa
2662 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2663 if(uReturn) {
2664 return uReturn;
2665 }
2666
2667 // Error out if too large on the plus side for an int64_t
2668 if(uResult > INT64_MAX) {
2669 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2670 }
2671
2672 // Error out if too large on the negative side for an int64_t
2673 if(uResult < (uint64_t)INT64_MAX+1) {
2674 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2675 of INT64_MIN. This assumes two's compliment representation where
2676 INT64_MIN is one increment farther from 0 than INT64_MAX.
2677 Trying to write -INT64_MIN doesn't work to get this because the
2678 compiler tries to work with an int64_t which can't represent
2679 -INT64_MIN.
2680 */
2681 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2682 }
2683
2684 // Casts are safe because of checks above
2685 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2686
2687 return QCBOR_SUCCESS;
2688}
2689
2690
2691static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2692{
2693 if(nMantissa < 0) {
2694 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2695 }
2696
2697 // Cast to unsigned is OK because of check for negative
2698 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2699 // Exponentiation is straight forward
2700 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2701}
2702
2703
2704// TODO: use this or get rid of it
2705QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2706{
2707 uint64_t uResult;
2708
2709 QCBORError uR;
2710
2711 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2712 if(uR) {
2713 return uR;
2714 }
2715
2716 if(uResult > INT64_MAX) {
2717 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2718 }
2719
2720 // Cast is OK because of check above
2721 *pnResult = (int64_t)uResult;
2722
2723 return QCBOR_SUCCESS;
2724}
2725
2726
2727
2728
2729#include <math.h>
2730/*
2731static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2732{
2733 // TODO: checkout exceptions; what is HUGE_VAL?
2734 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2735
2736 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002737 return 0;
2738}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002739*/
2740
2741
2742
2743
2744
Laurence Lundbladee6430642020-03-14 21:15:44 -07002745
2746/*
2747 A) bignum is positive
2748 A1) output is signed INT64_MAX
2749 A2) output is unsigned UINT64_MAX
2750 B) bignum is negative
2751 B1) output is signed INT64_MAX
2752 B2) output is unsigned error
2753 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002754static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002755{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002756 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002757
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002758 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002759 const uint8_t *pByte = BigNum.ptr;
2760 size_t uLen = BigNum.len;
2761 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002762 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002763 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002764 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002765 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002766 }
2767
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002768 *pResult = uResult;
2769 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002770}
2771
Laurence Lundbladec4537442020-04-14 18:53:22 -07002772
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002773#if 0
2774static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002775{
2776 double nResult;
2777
2778 nResult = 0;
2779 const uint8_t *pByte = BigNum.ptr;
2780 size_t uLen = BigNum.len;
2781 /* This will overflow and become the float value INFINITY if the number
2782 is too large to fit. No error will be logged.
2783 TODO: should an error be logged? */
2784 while(uLen--) {
2785 nResult = (nResult * 256) + *pByte;
2786 }
2787
2788 *pResult = nResult;
2789 return 0;
2790}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002791#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002792
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002793static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002794{
2795 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2796}
2797
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002798static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002799{
2800 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002801 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002802 if(n) {
2803 return n;
2804 }
2805 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2806 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002807 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002808}
2809
2810
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002811static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002812{
2813 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002814 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002815 if(n) {
2816 return n;
2817 }
2818 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2819 *pResult = -(int64_t)uResult;
2820 return 0;
2821}
2822
Laurence Lundbladec4537442020-04-14 18:53:22 -07002823// No function to convert a negative bignum to unsigned; it is an error
2824
2825
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002826#if 0
2827static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002828{
2829 int64_t nMantissa;
2830
2831 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2832 if(xx) {
2833 return xx;
2834 }
2835
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002836 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002837}
2838
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002839#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002840
2841
Laurence Lundbladee6430642020-03-14 21:15:44 -07002842
Laurence Lundbladec4537442020-04-14 18:53:22 -07002843
2844/*
2845 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2846 a big float, a decimal fraction or a big num. Conversion will be dones as
2847 expected. Some cases will error out with under or over flow.
2848 */
2849void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002850{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002851 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002852 return;
2853 }
2854
Laurence Lundbladee6430642020-03-14 21:15:44 -07002855 QCBORItem Item;
2856 QCBORError nError;
2857
2858 nError = QCBORDecode_GetNext(pMe, &Item);
2859 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002860 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002861 return;
2862 }
2863
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002864 if(pItem) {
2865 *pItem = Item;
2866 }
2867
Laurence Lundbladee6430642020-03-14 21:15:44 -07002868 switch(Item.uDataType) {
2869 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002870 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002871 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002872 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladee6430642020-03-14 21:15:44 -07002873 *pValue = (int64_t)Item.val.dfnum;
2874 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002875 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002876 }
2877 break;
2878
2879 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002880 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002881 *pValue = Item.val.int64;
2882 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002883 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002884 }
2885 break;
2886
2887 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002888 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002889 if(Item.val.uint64 < INT64_MAX) {
2890 *pValue = Item.val.int64;
2891 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002892 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002893 }
2894 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002895 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002896 }
2897 break;
2898
Laurence Lundbladec4537442020-04-14 18:53:22 -07002899 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002900 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002901 }
2902}
2903
2904/* This works for signed, unsigned and float */
2905void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2906{
2907 QCBORItem Item;
2908 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2909}
2910
2911
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002912// TODO make this inline
2913void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2914{
2915 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2916}
2917
2918
Laurence Lundbladec4537442020-04-14 18:53:22 -07002919
2920/*
2921 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2922 a big float, a decimal fraction or a big num. Conversion will be dones as
2923 expected. Some cases will error out with under or over flow.
2924 */
2925void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2926{
2927 QCBORItem Item;
2928
2929 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2930
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002931 if(pMe->uLastError == QCBOR_SUCCESS) {
2932 // The above conversion succeeded
2933 return;
2934 }
2935
2936 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2937 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002938 return;
2939 }
2940
2941 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002942
2943 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002944 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002945 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002946 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002947 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002948 }
2949 break;
2950
2951 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002952 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002953 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002954 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002955 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002956 }
2957 break;
2958
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002959#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2960 case QCBOR_TYPE_DECIMAL_FRACTION:
2961 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002962 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002963 Item.val.expAndMantissa.nExponent,
2964 pValue,
2965 &Exponentitate10UU);
2966 } else {
2967 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2968 }
2969 break;
2970
2971 case QCBOR_TYPE_BIGFLOAT:
2972 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002973 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002974 Item.val.expAndMantissa.nExponent,
2975 pValue,
2976 &Exponentitate2UU);
2977 } else {
2978 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2979 }
2980 break;
2981
2982
Laurence Lundbladee6430642020-03-14 21:15:44 -07002983 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002984 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002985 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002986 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002987 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002988 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002989 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002990 pValue,
2991 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002992 }
2993 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002994 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002995 }
2996 break;
2997
2998 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002999 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003000 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003001 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003002 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003003 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003004 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003005 pValue,
3006 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003007 }
3008 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003009 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003010 }
3011 break;
3012
3013 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003014 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003015 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003016 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003017 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003018 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003019 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003020 pValue,
3021 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003022 }
3023 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003024 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003025 }
3026 break;
3027
3028 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003029 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003030 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003031 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003032 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003033 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003034 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003035 pValue,
3036 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003037 }
3038 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003039 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003040 }
3041 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003042
3043 default:
3044 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3045#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003046 }
3047}
3048
Laurence Lundbladec4537442020-04-14 18:53:22 -07003049
3050
3051void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
3052{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003053 if(pMe->uLastError != QCBOR_SUCCESS) {
3054 return;
3055 }
3056
Laurence Lundbladec4537442020-04-14 18:53:22 -07003057 QCBORItem Item;
3058 QCBORError nError;
3059
3060 nError = QCBORDecode_GetNext(pMe, &Item);
3061 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003062 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003063 return;
3064 }
3065
3066 switch(Item.uDataType) {
3067 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003068 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003069 if(Item.val.dfnum >= 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003070 // TODO: over/underflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07003071 *pValue = (uint64_t)Item.val.dfnum;
3072 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003073 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003074 }
3075 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003076 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003077 }
3078 break;
3079
3080 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003081 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003082 if(Item.val.int64 >= 0) {
3083 *pValue = (uint64_t)Item.val.int64;
3084 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003085 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003086 }
3087 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003088 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003089 }
3090 break;
3091
3092 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003093 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003094 *pValue = Item.val.uint64;
3095 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003096 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003097 }
3098 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003099
3100 default:
3101 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003102 }
3103}
3104
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003105
3106/* This works for signed, unsigned and float */
3107void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003108{
3109 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003110 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3111}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003112
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003113
3114// TODO make this inline
3115void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3116{
3117 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3118}
3119
3120
3121
3122
3123void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3124{
3125 QCBORItem Item;
3126
3127 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3128
3129 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003130 return;
3131 }
3132
Laurence Lundbladee6430642020-03-14 21:15:44 -07003133 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003134
3135 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003136 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003137 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003138 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003139 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003140 }
3141 break;
3142
3143 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003144 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003145 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003146 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003147 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003148 }
3149 break;
3150
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003151#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3152
3153 case QCBOR_TYPE_DECIMAL_FRACTION:
3154 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003155 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003156 Item.val.expAndMantissa.nExponent,
3157 pValue,
3158 Exponentitate10UU);
3159 } else {
3160 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3161 }
3162 break;
3163
3164 case QCBOR_TYPE_BIGFLOAT:
3165 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003166 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003167 Item.val.expAndMantissa.nExponent,
3168 pValue,
3169 Exponentitate2UU);
3170 } else {
3171 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3172 }
3173 break;
3174
3175
3176
Laurence Lundbladee6430642020-03-14 21:15:44 -07003177 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003178 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003179 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003180 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003181 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003182 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003183 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003184 pValue,
3185 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003186 }
3187 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003188 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003189 }
3190 break;
3191
3192 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003193 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003194 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003195 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003196 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003197 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003198 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003199 pValue,
3200 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003201 }
3202 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003203 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003204 }
3205 break;
3206
3207 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003208 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003209 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003210 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003211 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003212 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003213 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003214 pValue,
3215 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003216 }
3217 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003218 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003219 }
3220 break;
3221
3222 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003223 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003224 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003225 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003226 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003227 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003228 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003229 pValue,
3230 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003231 }
3232 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003233 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003234 }
3235 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003236#endif
3237 default:
3238 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003239 }
3240}
3241
Laurence Lundbladec4537442020-04-14 18:53:22 -07003242
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003243
3244#if 0
Laurence Lundbladec4537442020-04-14 18:53:22 -07003245/*
3246
3247 Convert from bignums,
3248
3249 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003250void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003251{
3252 /* the same range of conversions */
3253
Laurence Lundbladec4537442020-04-14 18:53:22 -07003254 /* Conversion from bignums, decimal fractions and such will be interesting */
3255
3256 QCBORItem Item;
3257 QCBORError nError;
3258
3259 nError = QCBORDecode_GetNext(pMe, &Item);
3260 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003261 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003262 return;
3263 }
3264
Laurence Lundbladec4537442020-04-14 18:53:22 -07003265
3266 switch(Item.uDataType) {
3267 case QCBOR_TYPE_FLOAT:
3268 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3269 *pValue = Item.val.dfnum;
3270 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003271 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003272 }
3273 break;
3274
3275 case QCBOR_TYPE_INT64:
3276 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3277 // TODO: how does this work?
3278 *pValue = (double)Item.val.int64;
3279 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003280 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003281 }
3282 break;
3283
3284 case QCBOR_TYPE_UINT64:
3285 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3286 *pValue = (double)Item.val.uint64;
3287 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003288 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003289 }
3290 break;
3291
3292 case QCBOR_TYPE_DECIMAL_FRACTION:
3293 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003294 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003295 Item.val.expAndMantissa.nExponent,
3296 pValue);
3297 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003298 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003299 }
3300 break;
3301
3302 case QCBOR_TYPE_BIGFLOAT:
3303 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003304 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003305 Item.val.expAndMantissa.nExponent,
3306 pValue);
3307 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003308 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003309 }
3310 break;
3311
3312 case QCBOR_TYPE_POSBIGNUM:
3313 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003314 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003316 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003317 }
3318 break;
3319
3320 case QCBOR_TYPE_NEGBIGNUM:
3321 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003322 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003323 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003324 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003325 }
3326 break;
3327
3328 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3329 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3330 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003331 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3332 if(!pMe->uLastError) {
3333 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003334 Item.val.expAndMantissa.nExponent,
3335 pValue);
3336 }
3337 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003338 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003339 }
3340 break;
3341
3342 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3343 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3344 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003345 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3346 if(!pMe->uLastError) {
3347 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003348 Item.val.expAndMantissa.nExponent,
3349 pValue);
3350 }
3351 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003352 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003353 }
3354 break;
3355
3356 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3357 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3358 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003359 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3360 if(!pMe->uLastError) {
3361 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003362 Item.val.expAndMantissa.nExponent,
3363 pValue);
3364 }
3365 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003366 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003367 }
3368 break;
3369
3370 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3371 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3372 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003373 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3374 if(!pMe->uLastError) {
3375 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003376 Item.val.expAndMantissa.nExponent,
3377 pValue);
3378 }
3379 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003380 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003381 }
3382 break;
3383 }
3384
3385
3386
Laurence Lundbladee6430642020-03-14 21:15:44 -07003387}
3388
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003389#endif