blob: 7304b6a63ab3e98f8bd1d1479ff72826b6f50b02 [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 Lundblade9c905e82020-04-25 11:31:38 -0700134// Determine if at the end of a map or array, taking into
135// account map mode. If this returns true, it is OK
136// to get another item.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700137inline static bool
138DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
139{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700140 if(DecodeNesting_IsAtTop(pNesting)){
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700141 // Always at end if at the top level of nesting
142 return true;
143 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700144
145 if(pNesting->pCurrent->uMapMode) {
146 if(pNesting->pCurrent->uCount == 0) {
147 // In map mode and consumed all items, so it is the end
148 return true;
149 } else {
150 // In map mode, all items not consumed, so it is NOT the end
151 return false;
152 }
153 } else {
154 // Not in map mode, and not at top level so it NOT the end.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700155 return false;
156 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700157}
158
159
Laurence Lundbladeee851742020-01-08 08:37:05 -0800160inline static int
161DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700162{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700163 return pNesting->pCurrent->uCount == UINT16_MAX;
164}
165
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700166inline static int
167DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
168{
169 return (bool)pNesting->pCurrent->uMapMode;
170}
171
Laurence Lundbladeee851742020-01-08 08:37:05 -0800172inline static uint8_t
173DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800174{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800175 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700176 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800177 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178}
179
Laurence Lundbladeee851742020-01-08 08:37:05 -0800180inline static int
181DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700182{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700183 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700185 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800186
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
188}
189
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800190// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800191inline static QCBORError
192DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700193{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800194 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700195 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800196 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800198
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800199 // breaks can only occur when the map/array is indefinite length
200 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
201 return QCBOR_ERR_BAD_BREAK;
202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800203
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800204 // if all OK, the break reduces the level of nesting
205 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800206
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800207 return QCBOR_SUCCESS;
208}
209
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700210// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700211/* Decrements the map/array counter if possible. If decrement
212 closed out a map or array, then level up in nesting and decrement
213 again, until, the top is reached or the end of a map mode is reached
214 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800215inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700216DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800217{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700218 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700219 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800220
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800221 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700222 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800223 pNesting->pCurrent->uCount--;
224 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700225
226 if(pNesting->pCurrent->uCount != 0) {
227 // Did not close out an array or map, so nothing further
228 break;
229 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700230
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700231 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700232 // In map mode the level-up must be done explicitly
233 break;
234 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700235
236 // Closed out an array or map so level up
237 pNesting->pCurrent--;
238
239 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240 }
241}
242
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700243inline static void
244DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
245{
246 pNesting->pCurrent->uMapMode = 1;
247 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
248 pNesting->pCurrent->uOffset = (uint32_t)uOffset;
249}
250
251inline static void
252DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
253{
254 pNesting->pCurrent->uMapMode = 0;
255 pNesting->pCurrent--;
256
257 DecodeNesting_DecrementCount(pNesting);
258}
259
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800260// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800261inline static QCBORError
262DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700264 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800265
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800266 if(pItem->val.uCount == 0) {
267 // Nothing to do for empty definite lenth arrays. They are just are
268 // effectively the same as an item that is not a map or array
269 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530270 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800271 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800272
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800273 // Error out if arrays is too long to handle
274 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
276 goto Done;
277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800278
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800279 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
281 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
282 goto Done;
283 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800284
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800285 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800287
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800288 // Record a few details for this nesting level
289 pNesting->pCurrent->uMajorType = pItem->uDataType;
290 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700291 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700292 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800293
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700294Done:
295 return nReturn;;
296}
297
Laurence Lundbladeee851742020-01-08 08:37:05 -0800298inline static void
299DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700300{
301 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
302}
303
304
305
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306/*
307 This list of built-in tags. Only add tags here that are
308 clearly established and useful. Once a tag is added here
309 it can't be taken out as that would break backwards compatibility.
310 There are only 48 slots available forever.
311 */
312static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800313 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
314 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
315 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
316 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
317 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
318 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319 CBOR_TAG_COSE_ENCRYPTO,
320 CBOR_TAG_COSE_MAC0,
321 CBOR_TAG_COSE_SIGN1,
322 CBOR_TAG_ENC_AS_B64URL,
323 CBOR_TAG_ENC_AS_B64,
324 CBOR_TAG_ENC_AS_B16,
325 CBOR_TAG_CBOR,
326 CBOR_TAG_URI,
327 CBOR_TAG_B64URL,
328 CBOR_TAG_B64,
329 CBOR_TAG_REGEX,
330 CBOR_TAG_MIME,
331 CBOR_TAG_BIN_UUID,
332 CBOR_TAG_CWT,
333 CBOR_TAG_ENCRYPT,
334 CBOR_TAG_MAC,
335 CBOR_TAG_SIGN,
336 CBOR_TAG_GEO_COORD,
337 CBOR_TAG_CBOR_MAGIC
338};
339
340// This is used in a bit of cleverness in GetNext_TaggedItem() to
341// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800342// these types. This will break if the first six items in
343// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
344// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
345#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
346#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
347#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
348#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
349#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
350#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700351
Laurence Lundblade59289e52019-12-30 13:44:37 -0800352#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
353 QCBOR_TAGFLAG_DATE_EPOCH |\
354 QCBOR_TAGFLAG_POS_BIGNUM |\
355 QCBOR_TAGFLAG_NEG_BIGNUM |\
356 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
357 QCBOR_TAGFLAG_BIGFLOAT)
358
359#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
360 QCBOR_TAGFLAG_DATE_EPOCH |\
361 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700362 QCBOR_TAGFLAG_NEG_BIGNUM)
363
364#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
365#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
366#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
367
368static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
369{
370 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800371 /*
372 This is a cross-check to make sure the above array doesn't
373 accidentally get made too big. In normal conditions the above
374 test should optimize out as all the values are known at compile
375 time.
376 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700377 return -1;
378 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800379
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700380 if(uTag > UINT16_MAX) {
381 // This tag map works only on 16-bit tags
382 return -1;
383 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800384
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700385 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
386 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
387 return nTagBitIndex;
388 }
389 }
390 return -1; // Indicates no match
391}
392
393static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
394{
395 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
396 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
397 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
398 }
399 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700401 return -1; // Indicates no match
402}
403
404/*
405 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800406
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700407 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800408 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700409 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800410static QCBORError
411TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
412 uint64_t uTag,
413 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700414{
415 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
416 if(nTagBitIndex >= 0) {
417 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
418 *puTagBitIndex = (uint8_t)nTagBitIndex;
419 return QCBOR_SUCCESS;
420 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800421
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700422 if(pCallerConfiguredTagMap) {
423 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
424 return QCBOR_ERR_TOO_MANY_TAGS;
425 }
426 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
427 if(nTagBitIndex >= 0) {
428 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
429
430 *puTagBitIndex = (uint8_t)nTagBitIndex;
431 return QCBOR_SUCCESS;
432 }
433 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800434
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700435 return QCBOR_ERR_BAD_OPT_TAG;
436}
437
438
439
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800441 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
442
443 The following four functions are pretty wrappers for invocation of
444 the string allocator supplied by the caller.
445
Laurence Lundbladeee851742020-01-08 08:37:05 -0800446 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800447
Laurence Lundbladeee851742020-01-08 08:37:05 -0800448static inline void
449StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800450{
451 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
452}
453
Laurence Lundbladeee851742020-01-08 08:37:05 -0800454// StringAllocator_Reallocate called with pMem NULL is
455// equal to StringAllocator_Allocate()
456static inline UsefulBuf
457StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
458 void *pMem,
459 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800460{
461 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
462}
463
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464static inline UsefulBuf
465StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800466{
467 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
468}
469
Laurence Lundbladeee851742020-01-08 08:37:05 -0800470static inline void
471StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800472{
473 if(pMe->pfAllocator) {
474 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
475 }
476}
477
478
479
Laurence Lundbladeee851742020-01-08 08:37:05 -0800480/*===========================================================================
481 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800483 See qcbor/qcbor_decode.h for definition of the object
484 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800485 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700486/*
487 Public function, see header file
488 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800489void QCBORDecode_Init(QCBORDecodeContext *me,
490 UsefulBufC EncodedCBOR,
491 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700492{
493 memset(me, 0, sizeof(QCBORDecodeContext));
494 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800495 // Don't bother with error check on decode mode. If a bad value is
496 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700497 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700498 DecodeNesting_Init(&(me->nesting));
499}
500
501
502/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700503 Public function, see header file
504 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800505void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
506 QCBORStringAllocate pfAllocateFunction,
507 void *pAllocateContext,
508 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700509{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800510 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
511 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
512 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700513}
514
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515
516/*
517 Public function, see header file
518 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
520 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700521{
522 me->pCallerConfiguredTagList = pTagList;
523}
524
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700525
526/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527 This decodes the fundamental part of a CBOR data item, the type and
528 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800529
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532 This does the network->host byte order conversion. The conversion
533 here also results in the conversion for floats in addition to that
534 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800535
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700536 This returns:
537 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800539 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540 tags and floats and length for strings and arrays
541
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800542 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800543 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800544
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800545 The int type is preferred to uint8_t for some variables as this
546 avoids integer promotions, can reduce code size and makes
547 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700548 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800549inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
550 int *pnMajorType,
551 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800552 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700554 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800557 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800560 const int nTmpMajorType = nInitialByte >> 5;
561 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800563 // Where the number or argument accumulates
564 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800565
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800566 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567 // Need to get 1,2,4 or 8 additional argument bytes Map
568 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800569 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800570
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800571 // Loop getting all the bytes in the argument
572 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800573 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800574 // This shift and add gives the endian conversion
575 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
576 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800577 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800578 // The reserved and thus-far unused additional info values
579 nReturn = QCBOR_ERR_UNSUPPORTED;
580 goto Done;
581 } else {
582 // Less than 24, additional info is argument or 31, an indefinite length
583 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800584 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800586
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587 if(UsefulInputBuf_GetError(pUInBuf)) {
588 nReturn = QCBOR_ERR_HIT_END;
589 goto Done;
590 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592 // All successful if we got here.
593 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800594 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800595 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800596 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800597
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598Done:
599 return nReturn;
600}
601
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800604 CBOR doesn't explicitly specify two's compliment for integers but all
605 CPUs use it these days and the test vectors in the RFC are so. All
606 integers in the CBOR structure are positive and the major type
607 indicates positive or negative. CBOR can express positive integers
608 up to 2^x - 1 where x is the number of bits and negative integers
609 down to 2^x. Note that negative numbers can be one more away from
610 zero than positive. Stdint, as far as I can tell, uses two's
611 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 used carefully here, and in particular why it isn't used in the interface.
615 Also see
616 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
617
618 Int is used for values that need less than 16-bits and would be subject
619 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800621inline static QCBORError
622DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700624 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800625
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
627 if (uNumber <= INT64_MAX) {
628 pDecodedItem->val.int64 = (int64_t)uNumber;
629 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 } else {
632 pDecodedItem->val.uint64 = uNumber;
633 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 }
636 } else {
637 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 // CBOR's representation of negative numbers lines up with the
639 // two-compliment representation. A negative integer has one
640 // more in range than a positive integer. INT64_MIN is
641 // equal to (-INT64_MAX) - 1.
642 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700643 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800644
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 } else {
646 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000647 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648 nReturn = QCBOR_ERR_INT_OVERFLOW;
649 }
650 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652 return nReturn;
653}
654
655// Make sure #define value line up as DecodeSimple counts on this.
656#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
657#error QCBOR_TYPE_FALSE macro value wrong
658#endif
659
660#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
661#error QCBOR_TYPE_TRUE macro value wrong
662#endif
663
664#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
665#error QCBOR_TYPE_NULL macro value wrong
666#endif
667
668#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
669#error QCBOR_TYPE_UNDEF macro value wrong
670#endif
671
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700672#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
673#error QCBOR_TYPE_BREAK macro value wrong
674#endif
675
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
677#error QCBOR_TYPE_DOUBLE macro value wrong
678#endif
679
680#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
681#error QCBOR_TYPE_FLOAT macro value wrong
682#endif
683
684/*
685 Decode true, false, floats, break...
686 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800687inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800688DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700690 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladeee851742020-01-08 08:37:05 -0800692 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 // above make sure uAdditionalInfo values line up with uDataType values.
694 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
695 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800697 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800698 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
699 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700701 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700702 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
703 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700704 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700705 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700706 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
707 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700708 break;
709 case DOUBLE_PREC_FLOAT:
710 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700711 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700712 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 case CBOR_SIMPLEV_FALSE: // 20
715 case CBOR_SIMPLEV_TRUE: // 21
716 case CBOR_SIMPLEV_NULL: // 22
717 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700718 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700719 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 case CBOR_SIMPLEV_ONEBYTE: // 24
722 if(uNumber <= CBOR_SIMPLE_BREAK) {
723 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700724 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 goto Done;
726 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800727 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800729
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 default: // 0-19
731 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800732 /*
733 DecodeTypeAndNumber will make uNumber equal to
734 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
735 safe because the 2, 4 and 8 byte lengths of uNumber are in
736 the double/float cases above
737 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700738 pDecodedItem->val.uSimple = (uint8_t)uNumber;
739 break;
740 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742Done:
743 return nReturn;
744}
745
746
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700747/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530748 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800750inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
751 int nMajorType,
752 uint64_t uStrLen,
753 UsefulInputBuf *pUInBuf,
754 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700756 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
759 // This check makes the casts to size_t below safe.
760
761 // 4 bytes less than the largest sizeof() so this can be tested by
762 // putting a SIZE_MAX length in the CBOR test input (no one will
763 // care the limit on strings is 4 bytes shorter).
764 if(uStrLen > SIZE_MAX-4) {
765 nReturn = QCBOR_ERR_STRING_TOO_LONG;
766 goto Done;
767 }
768
769 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530770 if(UsefulBuf_IsNULLC(Bytes)) {
771 // Failed to get the bytes for this string item
772 nReturn = QCBOR_ERR_HIT_END;
773 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700774 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530775
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800776 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530777 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800778 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530779 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700780 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530781 goto Done;
782 }
783 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800784 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530785 } else {
786 // Normal case with no string allocator
787 pDecodedItem->val.string = Bytes;
788 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800790 // Cast because ternary operator causes promotion to integer
791 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
792 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530794Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700795 return nReturn;
796}
797
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800
801
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700802
803
Laurence Lundbladeee851742020-01-08 08:37:05 -0800804// Make sure the constants align as this is assumed by
805// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
807#error QCBOR_TYPE_ARRAY value not lined up with major type
808#endif
809#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
810#error QCBOR_TYPE_MAP value not lined up with major type
811#endif
812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800814 This gets a single data item and decodes it including preceding
815 optional tagging. This does not deal with arrays and maps and nesting
816 except to decode the data item introducing them. Arrays and maps are
817 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800818
Laurence Lundbladeee851742020-01-08 08:37:05 -0800819 Errors detected here include: an array that is too long to decode,
820 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800822static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
823 QCBORItem *pDecodedItem,
824 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700825{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700826 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800827
Laurence Lundbladeee851742020-01-08 08:37:05 -0800828 /*
829 Get the major type and the number. Number could be length of more
830 bytes or the value depending on the major type nAdditionalInfo is
831 an encoding of the length of the uNumber and is needed to decode
832 floats and doubles
833 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800834 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700835 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800836 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800837
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700838 memset(pDecodedItem, 0, sizeof(QCBORItem));
839
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800840 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundbladeee851742020-01-08 08:37:05 -0800842 // Error out here if we got into trouble on the type and number. The
843 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700844 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladeee851742020-01-08 08:37:05 -0800848 // At this point the major type and the value are valid. We've got
849 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700851 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
852 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700854 nReturn = QCBOR_ERR_BAD_INT;
855 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800856 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700857 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700858 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800859
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
861 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800862 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
863 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
864 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
865 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530866 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700867 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 }
870 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700872 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
873 case CBOR_MAJOR_TYPE_MAP: // Major type 5
874 // Record the number of items in the array or map
875 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
876 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
877 goto Done;
878 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800879 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530880 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800882 // type conversion OK because of check above
883 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800885 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
887 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700888 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800891 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700892 nReturn = QCBOR_ERR_BAD_INT;
893 } else {
894 pDecodedItem->val.uTagV = uNumber;
895 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
896 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800898
Laurence Lundbladeee851742020-01-08 08:37:05 -0800899 case CBOR_MAJOR_TYPE_SIMPLE:
900 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800901 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundbladeee851742020-01-08 08:37:05 -0800904 default:
905 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 nReturn = QCBOR_ERR_UNSUPPORTED;
907 break;
908 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800909
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910Done:
911 return nReturn;
912}
913
914
915
916/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800917 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800918 individual chunk items together into one QCBORItem using the string
919 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800920
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530921 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923static inline QCBORError
924GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700925{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700926 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700927
928 // Get pointer to string allocator. First use is to pass it to
929 // GetNext_Item() when option is set to allocate for *every* string.
930 // Second use here is to allocate space to coallese indefinite
931 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800932 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
933 &(me->StringAllocator) :
934 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800935
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700936 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800937 nReturn = GetNext_Item(&(me->InBuf),
938 pDecodedItem,
939 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 if(nReturn) {
941 goto Done;
942 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700944 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530945 // code in this function from here down can be eliminated. Run tests, except
946 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800948 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700949 const uint8_t uStringType = pDecodedItem->uDataType;
950 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 goto Done; // no need to do any work here on non-string types
952 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800954 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530955 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800956 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530959 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800960 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
962 goto Done;
963 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700965 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700966 UsefulBufC FullString = NULLUsefulBufC;
967
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700969 // Get item for next chunk
970 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700971 // NULL string allocator passed here. Do not need to allocate
972 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800973 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700975 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530978 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700979 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800980 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530982 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 break;
984 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800985
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700986 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530987 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700988 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 if(StringChunkItem.uDataType != uStringType ||
990 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700991 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 break;
993 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800994
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530995 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800996 // The first time throurgh FullString.ptr is NULL and this is
997 // equivalent to StringAllocator_Allocate()
998 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
999 UNCONST_POINTER(FullString.ptr),
1000 FullString.len + StringChunkItem.val.string.len);
1001
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301003 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001004 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 break;
1006 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001007
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001008 // Copy new string chunk at the end of string so far.
1009 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001012 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1013 // Getting the item failed, clean up the allocated memory
1014 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001016
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001017Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 return nReturn;
1019}
1020
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001021
1022/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001023 Gets all optional tag data items preceding a data item that is not an
1024 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001025 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001026static QCBORError
1027GetNext_TaggedItem(QCBORDecodeContext *me,
1028 QCBORItem *pDecodedItem,
1029 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001030{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001031 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001032 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001033 uint64_t uTagBits = 0;
1034 if(pTags) {
1035 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001037
Laurence Lundblade59289e52019-12-30 13:44:37 -08001038 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001039 for(;;) {
1040 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001042 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001043 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001045 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1046 // Successful exit from loop; maybe got some tags, maybe not
1047 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001048 break;
1049 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001051 uint8_t uTagBitIndex;
1052 // Tag was mapped, tag was not mapped, error with tag list
1053 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001055 case QCBOR_SUCCESS:
1056 // Successfully mapped the tag
1057 uTagBits |= 0x01ULL << uTagBitIndex;
1058 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001059
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001060 case QCBOR_ERR_BAD_OPT_TAG:
1061 // Tag is not recognized. Do nothing
1062 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001064 default:
1065 // Error Condition
1066 goto Done;
1067 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001068
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001069 if(pTags) {
1070 // Caller wants all tags recorded in the provided buffer
1071 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1072 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1073 goto Done;
1074 }
1075 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1076 pTags->uNumUsed++;
1077 }
1078 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001080Done:
1081 return nReturn;
1082}
1083
1084
1085/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001086 This layer takes care of map entries. It combines the label and data
1087 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001088 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001089static inline QCBORError
1090GetNext_MapEntry(QCBORDecodeContext *me,
1091 QCBORItem *pDecodedItem,
1092 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001093{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001094 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001095 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001096 if(nReturn)
1097 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001098
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001099 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001100 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001101 goto Done;
1102 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001103
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001104 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1105 // In a map and caller wants maps decoded, not treated as arrays
1106
1107 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1108 // If in a map and the right decoding mode, get the label
1109
Laurence Lundbladeee851742020-01-08 08:37:05 -08001110 // Save label in pDecodedItem and get the next which will
1111 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001112 QCBORItem LabelItem = *pDecodedItem;
1113 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1114 if(nReturn)
1115 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301117 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001118
1119 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1120 // strings are always good labels
1121 pDecodedItem->label.string = LabelItem.val.string;
1122 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1123 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001124 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001125 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1126 goto Done;
1127 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1128 pDecodedItem->label.int64 = LabelItem.val.int64;
1129 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1130 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1131 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1132 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1133 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1134 pDecodedItem->label.string = LabelItem.val.string;
1135 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1136 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1137 } else {
1138 // label is not an int or a string. It is an arrray
1139 // or a float or such and this implementation doesn't handle that.
1140 // Also, tags on labels are ignored.
1141 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1142 goto Done;
1143 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001144 }
1145 } else {
1146 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001147 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1148 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1149 goto Done;
1150 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001151 // Decoding a map as an array
1152 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001153 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1154 // Cast is needed because of integer promotion
1155 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001156 }
1157 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001158
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159Done:
1160 return nReturn;
1161}
1162
1163
1164/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001165 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001166 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001167 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001168QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1169 QCBORItem *pDecodedItem,
1170 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001171{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001172 // Stack ptr/int: 2, QCBORItem : 64
1173
Laurence Lundblade30816f22018-11-10 13:40:22 +07001174 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundblade1341c592020-04-11 14:19:05 -07001176 // Check if there are an TODO: incomplete comment
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001177 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001178 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1179 goto Done;
1180 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001181
1182 // This is to handle map and array mode
1183 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1184 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1185 goto Done;
1186 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001187
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001188 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001189 if(nReturn) {
1190 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001191 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301192
1193 // Break ending arrays/maps are always processed at the end of this function.
1194 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301195 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301196 nReturn = QCBOR_ERR_BAD_BREAK;
1197 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301198 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundblade6de37062018-10-15 12:22:42 +05301200 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301201 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301202 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade6de37062018-10-15 12:22:42 +05301204 // Process the item just received for descent or decrement, and
1205 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001206 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001207 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001208 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001209 // Maps and arrays do count in as items in the map/array that encloses
1210 // them so a decrement needs to be done for them too, but that is done
1211 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001212 // are opened with the exception of an empty map or array.
1213 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001214 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001215 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001216 } else {
1217 // Decrement the count of items in the enclosing map/array
1218 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301219 // triggers a decrement in the map/array above that and
1220 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001221 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001222 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301223 if(nReturn) {
1224 goto Done;
1225 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001226
Laurence Lundblade6de37062018-10-15 12:22:42 +05301227 // For indefinite length maps/arrays, looking at any and
1228 // all breaks that might terminate them. The equivalent
1229 // for definite length maps/arrays happens in
1230 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001231 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301232 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1233 // Peek forward one item to see if it is a break.
1234 QCBORItem Peek;
1235 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1236 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1237 if(nReturn) {
1238 goto Done;
1239 }
1240 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1241 // It is not a break, rewind so it can be processed normally.
1242 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1243 break;
1244 }
1245 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301246 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301247 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1248 if(nReturn) {
1249 // break occured outside of an indefinite length array/map
1250 goto Done;
1251 }
1252 }
1253 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001254
Laurence Lundblade6de37062018-10-15 12:22:42 +05301255 // Tell the caller what level is next. This tells them what maps/arrays
1256 // were closed out and makes it possible for them to reconstruct
1257 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001258 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1259 // At end of a map / array in map mode, so next nest is 0 to
1260 // indicate this end.
1261 pDecodedItem->uNextNestLevel = 0;
1262 } else {
1263 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1264 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001265
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001266Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001267 if(nReturn != QCBOR_SUCCESS) {
1268 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1269 memset(pDecodedItem, 0, sizeof(QCBORItem));
1270 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001271 return nReturn;
1272}
1273
1274
Laurence Lundblade59289e52019-12-30 13:44:37 -08001275/*
1276 Mostly just assign the right data type for the date string.
1277 */
1278inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1279{
1280 // Stack Use: UsefulBuf 1 16
1281 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1282 return QCBOR_ERR_BAD_OPT_TAG;
1283 }
1284
1285 const UsefulBufC Temp = pDecodedItem->val.string;
1286 pDecodedItem->val.dateString = Temp;
1287 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1288 return QCBOR_SUCCESS;
1289}
1290
1291
1292/*
1293 Mostly just assign the right data type for the bignum.
1294 */
1295inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1296{
1297 // Stack Use: UsefulBuf 1 -- 16
1298 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1299 return QCBOR_ERR_BAD_OPT_TAG;
1300 }
1301 const UsefulBufC Temp = pDecodedItem->val.string;
1302 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001303 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001304 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1305 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001306 return QCBOR_SUCCESS;
1307}
1308
1309
1310/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001311 The epoch formatted date. Turns lots of different forms of encoding
1312 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001313 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001314static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001315{
1316 // Stack usage: 1
1317 QCBORError nReturn = QCBOR_SUCCESS;
1318
1319 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1320
1321 switch (pDecodedItem->uDataType) {
1322
1323 case QCBOR_TYPE_INT64:
1324 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1325 break;
1326
1327 case QCBOR_TYPE_UINT64:
1328 if(pDecodedItem->val.uint64 > INT64_MAX) {
1329 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1330 goto Done;
1331 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001332 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001333 break;
1334
1335 case QCBOR_TYPE_DOUBLE:
1336 {
1337 // This comparison needs to be done as a float before
1338 // conversion to an int64_t to be able to detect doubles
1339 // that are too large to fit into an int64_t. A double
1340 // has 52 bits of preceision. An int64_t has 63. Casting
1341 // INT64_MAX to a double actually causes a round up which
1342 // is bad and wrong for the comparison because it will
1343 // allow conversion of doubles that can't fit into a
1344 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1345 // the cutoff point as if that rounds up in conversion to
1346 // double it will still be less than INT64_MAX. 0x7ff is
1347 // picked because it has 11 bits set.
1348 //
1349 // INT64_MAX seconds is on the order of 10 billion years,
1350 // and the earth is less than 5 billion years old, so for
1351 // most uses this conversion error won't occur even though
1352 // doubles can go much larger.
1353 //
1354 // Without the 0x7ff there is a ~30 minute range of time
1355 // values 10 billion years in the past and in the future
1356 // where this this code would go wrong.
1357 const double d = pDecodedItem->val.dfnum;
1358 if(d > (double)(INT64_MAX - 0x7ff)) {
1359 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1360 goto Done;
1361 }
1362 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1363 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1364 }
1365 break;
1366
1367 default:
1368 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1369 goto Done;
1370 }
1371 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1372
1373Done:
1374 return nReturn;
1375}
1376
1377
1378#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1379/*
1380 Decode decimal fractions and big floats.
1381
1382 When called pDecodedItem must be the array that is tagged as a big
1383 float or decimal fraction, the array that has the two members, the
1384 exponent and mantissa.
1385
1386 This will fetch and decode the exponent and mantissa and put the
1387 result back into pDecodedItem.
1388 */
1389inline static QCBORError
1390QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1391{
1392 QCBORError nReturn;
1393
1394 // --- Make sure it is an array; track nesting level of members ---
1395 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1396 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1397 goto Done;
1398 }
1399
1400 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001401 // definite length arrays, but not for indefnite. Instead remember
1402 // the nesting level the two integers must be at, which is one
1403 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001404 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1405
1406 // --- Is it a decimal fraction or a bigfloat? ---
1407 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1408 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1409
1410 // --- Get the exponent ---
1411 QCBORItem exponentItem;
1412 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1413 if(nReturn != QCBOR_SUCCESS) {
1414 goto Done;
1415 }
1416 if(exponentItem.uNestingLevel != nNestLevel) {
1417 // Array is empty or a map/array encountered when expecting an int
1418 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1419 goto Done;
1420 }
1421 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1422 // Data arriving as an unsigned int < INT64_MAX has been converted
1423 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1424 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1425 // will be too large for this to handle and thus an error that will
1426 // get handled in the next else.
1427 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1428 } else {
1429 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1430 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1431 goto Done;
1432 }
1433
1434 // --- Get the mantissa ---
1435 QCBORItem mantissaItem;
1436 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1437 if(nReturn != QCBOR_SUCCESS) {
1438 goto Done;
1439 }
1440 if(mantissaItem.uNestingLevel != nNestLevel) {
1441 // Mantissa missing or map/array encountered when expecting number
1442 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1443 goto Done;
1444 }
1445 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1446 // Data arriving as an unsigned int < INT64_MAX has been converted
1447 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1448 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1449 // will be too large for this to handle and thus an error that
1450 // will get handled in an else below.
1451 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1452 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1453 // Got a good big num mantissa
1454 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1455 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001456 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1457 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1458 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001459 } else {
1460 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1461 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1462 goto Done;
1463 }
1464
1465 // --- Check that array only has the two numbers ---
1466 if(mantissaItem.uNextNestLevel == nNestLevel) {
1467 // Extra items in the decimal fraction / big num
1468 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1469 goto Done;
1470 }
1471
1472Done:
1473
1474 return nReturn;
1475}
1476#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1477
1478
1479/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001480 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001481 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001482QCBORError
1483QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1484 QCBORItem *pDecodedItem,
1485 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001486{
1487 QCBORError nReturn;
1488
1489 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1490 if(nReturn != QCBOR_SUCCESS) {
1491 goto Done;
1492 }
1493
1494#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1495#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1496#else
1497#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1498#endif
1499
1500 // Only pay attention to tags this code knows how to decode.
1501 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1502 case 0:
1503 // No tags at all or none we know about. Nothing to do.
1504 // This is the pass-through path of this function
1505 // that will mostly be taken when decoding any item.
1506 break;
1507
1508 case QCBOR_TAGFLAG_DATE_STRING:
1509 nReturn = DecodeDateString(pDecodedItem);
1510 break;
1511
1512 case QCBOR_TAGFLAG_DATE_EPOCH:
1513 nReturn = DecodeDateEpoch(pDecodedItem);
1514 break;
1515
1516 case QCBOR_TAGFLAG_POS_BIGNUM:
1517 case QCBOR_TAGFLAG_NEG_BIGNUM:
1518 nReturn = DecodeBigNum(pDecodedItem);
1519 break;
1520
1521#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1522 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1523 case QCBOR_TAGFLAG_BIGFLOAT:
1524 // For aggregate tagged types, what goes into pTags is only collected
1525 // from the surrounding data item, not the contents, so pTags is not
1526 // passed on here.
1527
1528 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1529 break;
1530#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1531
1532 default:
1533 // Encountering some mixed-up CBOR like something that
1534 // is tagged as both a string and integer date.
1535 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1536 }
1537
1538Done:
1539 if(nReturn != QCBOR_SUCCESS) {
1540 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1541 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1542 }
1543 return nReturn;
1544}
1545
1546
1547/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001548 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001549 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001550QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001551{
1552 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1553}
1554
1555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001556/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301557 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301558 next one down. If a layer has no work to do for a particular item
1559 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundblade59289e52019-12-30 13:44:37 -08001561 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1562 tagged data items, turning them into the local C representation.
1563 For the most simple it is just associating a QCBOR_TYPE with the data. For
1564 the complex ones that an aggregate of data items, there is some further
1565 decoding and a little bit of recursion.
1566
1567 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301568 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301569 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001570 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001571
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301572 - GetNext_MapEntry -- This handles the combining of two
1573 items, the label and the data, that make up a map entry.
1574 It only does work on maps. It combines the label and data
1575 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001576
Laurence Lundblade59289e52019-12-30 13:44:37 -08001577 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1578 tags into bit flags associated with the data item. No actual decoding
1579 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001580
Laurence Lundblade59289e52019-12-30 13:44:37 -08001581 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301582 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301583 string allocater to create contiguous space for the item. It
1584 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001585
Laurence Lundblade59289e52019-12-30 13:44:37 -08001586 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1587 atomic data item has a "major type", an integer "argument" and optionally
1588 some content. For text and byte strings, the content is the bytes
1589 that make up the string. These are the smallest data items that are
1590 considered to be well-formed. The content may also be other data items in
1591 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001592
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001593 Roughly this takes 300 bytes of stack for vars. Need to
1594 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001595
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301596 */
1597
1598
1599/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001600 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001601 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001602int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1603 const QCBORItem *pItem,
1604 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001605{
1606 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001607
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001608 uint8_t uTagBitIndex;
1609 // Do not care about errors in pCallerConfiguredTagMap here. They are
1610 // caught during GetNext() before this is called.
1611 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1612 return 0;
1613 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001614
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001615 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1616 return (uTagBit & pItem->uTagBits) != 0;
1617}
1618
1619
1620/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001621 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001622 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001623QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001624{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001625 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001626
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001627 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001628 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001629 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1630 goto Done;
1631 }
1632
1633 // Error out if not all the bytes are consumed
1634 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1635 nReturn = QCBOR_ERR_EXTRA_BYTES;
1636 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001637
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001638Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301639 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001640 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001641 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001642
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001643 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001644}
1645
1646
1647
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001648/*
1649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001650Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001651
Laurence Lundbladeee851742020-01-08 08:37:05 -08001652 - Hit end of input before it was expected while decoding type and
1653 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001654
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001655 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001656
Laurence Lundbladeee851742020-01-08 08:37:05 -08001657 - Hit end of input while decoding a text or byte string
1658 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001659
Laurence Lundbladeee851742020-01-08 08:37:05 -08001660 - Encountered conflicting tags -- e.g., an item is tagged both a date
1661 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001662
Laurence Lundbladeee851742020-01-08 08:37:05 -08001663 - Encontered an array or mapp that has too many items
1664 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001665
Laurence Lundbladeee851742020-01-08 08:37:05 -08001666 - Encountered array/map nesting that is too deep
1667 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001668
Laurence Lundbladeee851742020-01-08 08:37:05 -08001669 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1670 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001671
Laurence Lundbladeee851742020-01-08 08:37:05 -08001672 - The type of a map label is not a string or int
1673 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001674
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001675 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001677 */
1678
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001679
1680
Laurence Lundbladef6531662018-12-04 10:42:22 +09001681
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001682/* ===========================================================================
1683 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001684
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001685 This implements a simple sting allocator for indefinite length
1686 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1687 implements the function type QCBORStringAllocate and allows easy
1688 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001689
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001690 This particular allocator is built-in for convenience. The caller
1691 can implement their own. All of this following code will get
1692 dead-stripped if QCBORDecode_SetMemPool() is not called.
1693
1694 This is a very primitive memory allocator. It does not track
1695 individual allocations, only a high-water mark. A free or
1696 reallocation must be of the last chunk allocated.
1697
1698 The size of the pool and offset to free memory are packed into the
1699 first 8 bytes of the memory pool so we don't have to keep them in
1700 the decode context. Since the address of the pool may not be
1701 aligned, they have to be packed and unpacked as if they were
1702 serialized data of the wire or such.
1703
1704 The sizes packed in are uint32_t to be the same on all CPU types
1705 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001706 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001707
1708
Laurence Lundbladeee851742020-01-08 08:37:05 -08001709static inline int
1710MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001711{
1712 // Use of UsefulInputBuf is overkill, but it is convenient.
1713 UsefulInputBuf UIB;
1714
Laurence Lundbladeee851742020-01-08 08:37:05 -08001715 // Just assume the size here. It was checked during SetUp so
1716 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001717 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1718 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1719 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1720 return UsefulInputBuf_GetError(&UIB);
1721}
1722
1723
Laurence Lundbladeee851742020-01-08 08:37:05 -08001724static inline int
1725MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001726{
1727 // Use of UsefulOutBuf is overkill, but convenient. The
1728 // length check performed here is useful.
1729 UsefulOutBuf UOB;
1730
1731 UsefulOutBuf_Init(&UOB, Pool);
1732 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1733 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1734 return UsefulOutBuf_GetError(&UOB);
1735}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001736
1737
1738/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001739 Internal function for an allocation, reallocation free and destuct.
1740
1741 Having only one function rather than one each per mode saves space in
1742 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001743
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001744 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1745 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001746static UsefulBuf
1747MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001748{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001749 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001750
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001751 uint32_t uPoolSize;
1752 uint32_t uFreeOffset;
1753
1754 if(uNewSize > UINT32_MAX) {
1755 // This allocator is only good up to 4GB. This check should
1756 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1757 goto Done;
1758 }
1759 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1760
1761 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1762 goto Done;
1763 }
1764
1765 if(uNewSize) {
1766 if(pMem) {
1767 // REALLOCATION MODE
1768 // Calculate pointer to the end of the memory pool. It is
1769 // assumed that pPool + uPoolSize won't wrap around by
1770 // assuming the caller won't pass a pool buffer in that is
1771 // not in legitimate memory space.
1772 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1773
1774 // Check that the pointer for reallocation is in the range of the
1775 // pool. This also makes sure that pointer math further down
1776 // doesn't wrap under or over.
1777 if(pMem >= pPool && pMem < pPoolEnd) {
1778 // Offset to start of chunk for reallocation. This won't
1779 // wrap under because of check that pMem >= pPool. Cast
1780 // is safe because the pool is always less than UINT32_MAX
1781 // because of check in QCBORDecode_SetMemPool().
1782 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1783
1784 // Check to see if the allocation will fit. uPoolSize -
1785 // uMemOffset will not wrap under because of check that
1786 // pMem is in the range of the uPoolSize by check above.
1787 if(uNewSize <= uPoolSize - uMemOffset) {
1788 ReturnValue.ptr = pMem;
1789 ReturnValue.len = uNewSize;
1790
1791 // Addition won't wrap around over because uNewSize was
1792 // checked to be sure it is less than the pool size.
1793 uFreeOffset = uMemOffset + uNewSize32;
1794 }
1795 }
1796 } else {
1797 // ALLOCATION MODE
1798 // uPoolSize - uFreeOffset will not underflow because this
1799 // pool implementation makes sure uFreeOffset is always
1800 // smaller than uPoolSize through this check here and
1801 // reallocation case.
1802 if(uNewSize <= uPoolSize - uFreeOffset) {
1803 ReturnValue.len = uNewSize;
1804 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001805 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001806 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001807 }
1808 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001809 if(pMem) {
1810 // FREE MODE
1811 // Cast is safe because of limit on pool size in
1812 // QCBORDecode_SetMemPool()
1813 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1814 } else {
1815 // DESTRUCT MODE
1816 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001817 }
1818 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001819
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001820 UsefulBuf Pool = {pPool, uPoolSize};
1821 MemPool_Pack(Pool, uFreeOffset);
1822
1823Done:
1824 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001825}
1826
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001827
Laurence Lundbladef6531662018-12-04 10:42:22 +09001828/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001829 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001830 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001831QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1832 UsefulBuf Pool,
1833 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001834{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001835 // The pool size and free mem offset are packed into the beginning
1836 // of the pool memory. This compile time check make sure the
1837 // constant in the header is correct. This check should optimize
1838 // down to nothing.
1839 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001840 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001841 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001842
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001843 // The pool size and free offset packed in to the beginning of pool
1844 // memory are only 32-bits. This check will optimize out on 32-bit
1845 // machines.
1846 if(Pool.len > UINT32_MAX) {
1847 return QCBOR_ERR_BUFFER_TOO_LARGE;
1848 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001849
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001850 // This checks that the pool buffer given is big enough.
1851 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1852 return QCBOR_ERR_BUFFER_TOO_SMALL;
1853 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001854
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001855 pMe->StringAllocator.pfAllocator = MemPool_Function;
1856 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1857 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001858
Laurence Lundblade30816f22018-11-10 13:40:22 +07001859 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001860}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001861
Laurence Lundblade1341c592020-04-11 14:19:05 -07001862#include <stdio.h>
1863void printdecode(QCBORDecodeContext *pMe, const char *szName)
1864{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001865 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1866 szName,
1867 (uint32_t)pMe->InBuf.cursor,
1868 (uint32_t)pMe->InBuf.UB.len);
1869/* for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
1870 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1871 break;
1872 }
1873 printf(" %2d %5d %s %6u %2d %d\n",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001874 i,
1875 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001876 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1877 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1878 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001879 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001880 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1881 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001882 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001883
Laurence Lundblade1341c592020-04-11 14:19:05 -07001884 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001885 printf("\n"); */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001886}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001887
1888
1889/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001890 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001891 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001892static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001893ConsumeItem(QCBORDecodeContext *pMe,
1894 const QCBORItem *pItemToConsume,
1895 uint_fast8_t *puNextNestLevel)
1896{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001897 QCBORError nReturn;
1898 QCBORItem Item;
1899
1900 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001901
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001902 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001903 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001904
Laurence Lundblade1341c592020-04-11 14:19:05 -07001905 /* This works for definite and indefinite length
1906 * maps and arrays by using the nesting level
1907 */
1908 do {
1909 nReturn = QCBORDecode_GetNext(pMe, &Item);
1910 if(nReturn != QCBOR_SUCCESS) {
1911 goto Done;
1912 }
1913 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001914
Laurence Lundblade1341c592020-04-11 14:19:05 -07001915 if(puNextNestLevel != NULL) {
1916 *puNextNestLevel = Item.uNextNestLevel;
1917 }
1918 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001919
Laurence Lundblade1341c592020-04-11 14:19:05 -07001920 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001921 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001922 if(puNextNestLevel != NULL) {
1923 /* Just pass the nesting level through */
1924 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1925 }
1926 nReturn = QCBOR_SUCCESS;
1927 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001928
1929Done:
1930 return nReturn;
1931}
1932
1933
Laurence Lundblade1341c592020-04-11 14:19:05 -07001934/* Return true if the labels in Item1 and Item2 are the same.
1935 Works only for integer and string labels. Returns false
1936 for any other type. */
1937static inline bool
1938MatchLabel(QCBORItem Item1, QCBORItem Item2)
1939{
1940 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1941 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1942 return true;
1943 }
1944 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001945 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001946 return true;
1947 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001948 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
1949 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1950 return true;
1951 }
1952 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1953 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
1954 return true;
1955 }
1956 }
1957
Laurence Lundblade1341c592020-04-11 14:19:05 -07001958 /* Other label types are never matched */
1959 return false;
1960}
1961
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001962static inline bool
1963MatchType(QCBORItem Item1, QCBORItem Item2)
1964{
1965 if(Item1.uDataType == Item2.uDataType) {
1966 return true;
1967 } else if(Item1.uLabelType == QCBOR_TYPE_ANY) {
1968 return true;
1969 } else if(Item2.uLabelType == QCBOR_TYPE_ANY) {
1970 return true;
1971 }
1972
1973 /* Other label types are never matched */
1974 return false;
1975}
1976
1977
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001978/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001979 On input pItemArray contains a list of labels and data types
1980 of items to be found.
1981
1982 On output the fully retrieved items are filled in with
1983 values and such. The label was matched, so it never changes.
1984
1985 If an item was not found, its data type is set to none.
1986
1987 TODO: type in and out is not right.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001988 */
1989QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001990GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001991{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001992 QCBORError nReturn;
1993
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001994 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
1995 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001996 }
1997
Laurence Lundblade1341c592020-04-11 14:19:05 -07001998 QCBORDecodeNesting N = pMe->nesting;
1999
2000 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2001 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2002 }
2003
2004 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2005
2006 /* Loop over all the items in the map. They could be
2007 * deeply nested and this should handle both definite
2008 * and indefinite length maps and arrays, so this
2009 * adds some complexity. */
2010 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
2011
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002012 uint_fast8_t uNextNestLevel;
2013
2014 uint64_t uFound = 0;
2015
2016 do {
2017 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002018 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002019
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002020 /* Get the item */
2021 QCBORItem Item;
2022 nReturn = QCBORDecode_GetNext(pMe, &Item);
2023 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002024 /* Got non-well-formed CBOR */
2025 goto Done;
2026 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002027
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002028 /* See if item has one of the labels that are of interest */
2029 int i;
2030 QCBORItem *pIterator;
2031 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002032 if(MatchLabel(Item, *pIterator)) {
2033 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002034 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002035 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2036 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002037 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002038 if(!MatchType(Item, *pIterator)) {
2039 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2040 goto Done;
2041 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002042
2043 /* Successful match. Return the item. */
2044 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002045 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002046 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002047 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002048 }
2049 }
2050 }
2051
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002052 /* Consume the item whether matched or not. This
2053 does th work of traversing maps and array and
2054 everything in them. In this loop only the
2055 items at the current nesting level are examined
2056 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002057 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2058 if(nReturn) {
2059 goto Done;
2060 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002061
2062 } while (uNextNestLevel >= uMapNestLevel);
2063
2064
2065 nReturn = QCBOR_SUCCESS;
2066
2067 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2068 // Cast OK because encoded CBOR is limited to UINT32_MAX
2069 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2070 // TODO: is zero *puOffset OK?
2071 if(puEndOffset) {
2072 *puEndOffset = uEndOffset;
2073 }
2074
2075 /* Mark all the ones not found */
2076 int i;
2077 QCBORItem *pIterator;
2078 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2079 if(!(uFound & (0x01ULL << i))) {
2080 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002081 }
2082 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002083
2084Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002085 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002086
Laurence Lundblade1341c592020-04-11 14:19:05 -07002087 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002088}
2089
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002090
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002091void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2092{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002093 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002094
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002095/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002096 if(pMe->uMapEndOffset) {
2097 uEndOffset = pMe->uMapEndOffset;
2098 // It is only valid once.
2099 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002100 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002101 QCBORItem Dummy;
2102
2103 Dummy.uLabelType = QCBOR_TYPE_NONE;
2104
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002105 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002106
2107 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002108// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002109
2110 printdecode(pMe, "start exit");
2111 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2112
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002113 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002114 printdecode(pMe, "end exit");
2115
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002116}
2117
2118
2119QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002120 int64_t nLabel,
2121 uint8_t uQcborType,
2122 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002123{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002124 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002125
Laurence Lundblade1341c592020-04-11 14:19:05 -07002126 One[0].uLabelType = QCBOR_TYPE_INT64;
2127 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002128 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002129 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2130
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002131 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002132 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002133 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134 }
2135
2136 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002137 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002138 }
2139
2140 *pItem = One[0];
2141
2142 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002143}
2144
2145
2146QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002147 const char *szLabel,
2148 uint8_t uQcborType,
2149 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002150{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002151 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002152
Laurence Lundblade1341c592020-04-11 14:19:05 -07002153 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2154 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002155 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002156 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2157
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002158 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002159 if(nReturn) {
2160 return nReturn;
2161 }
2162
2163 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002164 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002165 }
2166
2167 *pItem = One[0];
2168
2169 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002170}
2171
2172
Laurence Lundblade1341c592020-04-11 14:19:05 -07002173
Laurence Lundblade1341c592020-04-11 14:19:05 -07002174
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002175static int FinishEnter(QCBORDecodeContext *pMe, size_t uOffset)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002176{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002177 /* Seek to the data item that is the map or array */
2178 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2179
2180 /* Skip the data item that is the map or array */
2181 QCBORItem MapToEnter;
2182 // TODO: check error
2183 QCBORDecode_GetNext(pMe, &MapToEnter);
2184
2185 /* Enter map mode with an offset that is the first item
2186 in the map or array. */
2187 // TODO: what if map or array is empty?
2188 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
2189
2190
2191 printdecode(pMe, "Entered Map in Map");
2192
2193 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002194}
2195
2196
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002197QCBORError QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002198{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002199 /* Use GetItemsInMap to find the map by label, including the
2200 byte offset of it. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002201 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002202 One[0].uLabelType = QCBOR_TYPE_INT64;
2203 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002204 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002205 One[1].uLabelType = QCBOR_TYPE_NONE;
2206
2207 size_t uOffset;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002208 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002209 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002210 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002211 }
2212
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002213 /* The map to enter was found, now finish of entering it. */
2214 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002215
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002216 // TODO: error code?
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002218}
2219
2220
2221QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2222{
2223 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002224
Laurence Lundblade1341c592020-04-11 14:19:05 -07002225 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2226 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002227 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002228 One[1].uLabelType = QCBOR_TYPE_NONE;
2229
2230 size_t uOffset;
2231
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002232 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002233
2234 if(nReturn) {
2235 return nReturn;
2236 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002237
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002238 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002239
2240 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002241}
2242
2243
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002244QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002245{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002246 QCBORItem One[2];
2247
2248 One[0].uLabelType = QCBOR_TYPE_INT64;
2249 One[0].label.int64 = nLabel;
2250 One[0].uDataType = QCBOR_TYPE_ARRAY;
2251 One[1].uLabelType = QCBOR_TYPE_NONE;
2252
2253 size_t uOffset;
2254
2255 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
2256
2257 if(nReturn != QCBOR_SUCCESS) {
2258 return nReturn;
2259 }
2260
2261 FinishEnter(pMe, uOffset);
2262
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002263 return 0;
2264}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002265
Laurence Lundblade1341c592020-04-11 14:19:05 -07002266
2267QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2268{
2269 QCBORItem One[2];
2270
2271 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2272 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002273 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002274 One[1].uLabelType = QCBOR_TYPE_NONE;
2275
2276 size_t uOffset;
2277
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002278 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002279
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002280 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281 return nReturn;
2282 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002284 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285
2286 return 0;
2287}
2288
2289
2290
2291
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002292
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002293/* Next item must be map or this generates an error */
2294QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2295{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002296 QCBORItem Item;
2297 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002298
2299 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002300 nReturn = QCBORDecode_GetNext(pMe, &Item);
2301 if(nReturn != QCBOR_SUCCESS) {
2302 return nReturn;
2303 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002304 if(Item.uDataType != QCBOR_TYPE_MAP) {
2305 return QCBOR_ERR_UNEXPECTED_TYPE;
2306 }
2307
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002308 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002309
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002310 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002311
Laurence Lundblade1341c592020-04-11 14:19:05 -07002312 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313}
2314
2315
2316
2317QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2318{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002319 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002320}
2321
2322
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002323
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002324
2325
Laurence Lundblade1341c592020-04-11 14:19:05 -07002326void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002327{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002328 // TODO: check for map mode
2329 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2330 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2331}
2332
2333
2334QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2335{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002336 QCBORItem Item;
2337 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002338
2339 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002340 nReturn = QCBORDecode_GetNext(pMe, &Item);
2341 if(nReturn != QCBOR_SUCCESS) {
2342 return nReturn;
2343 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002344 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2345 return QCBOR_ERR_UNEXPECTED_TYPE;
2346 }
2347
2348 printdecode(pMe, "EnterArray");
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002349
2350 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002351
2352 return QCBOR_SUCCESS;
2353}
2354
2355
2356void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2357{
2358 // TODO: make sure we have entered an array
2359 // TODO: combine with code for map? It is the same so far.
2360 size_t uEndOffset;
2361
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002362 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002363 uEndOffset = pMe->uMapEndOffset;
2364 // It is only valid once.
2365 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002366 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002367 QCBORItem Dummy;
2368
2369 Dummy.uLabelType = QCBOR_TYPE_NONE;
2370
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002371 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002372
2373 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002374 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375
Laurence Lundblade1341c592020-04-11 14:19:05 -07002376 printdecode(pMe, "start exit");
2377 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2378
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002379 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002380 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002381}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002382
Laurence Lundbladee6430642020-03-14 21:15:44 -07002383
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002384void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2385{
2386 // TODO: error handling
2387 QCBORItem Item;
2388 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2389 *pInt = Item.val.int64;
2390}
2391
2392void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2393{
2394 // TODO: error handling
2395 QCBORItem Item;
2396 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2397 *pBstr = Item.val.string;
2398}
2399
2400void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2401{
2402 // TODO: error handling
2403 QCBORItem Item;
2404 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2405 *pBstr = Item.val.string;
2406}
2407
2408void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2409{
2410 // TODO: error handling
2411 QCBORItem Item;
2412 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2413 *pBstr = Item.val.string;
2414}
2415
Laurence Lundbladee6430642020-03-14 21:15:44 -07002416
Laurence Lundbladec4537442020-04-14 18:53:22 -07002417void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002418{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002419 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002420 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002421 return;
2422 }
2423
Laurence Lundbladec4537442020-04-14 18:53:22 -07002424 QCBORError nError;
2425 QCBORItem Item;
2426
2427 nError = QCBORDecode_GetNext(pMe, &Item);
2428 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002429 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002430 return;
2431 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002432
2433 switch(Item.uDataType) {
2434 case QCBOR_TYPE_TRUE:
2435 *pValue = true;
2436 break;
2437
2438 case QCBOR_TYPE_FALSE:
2439 *pValue = false;
2440 break;
2441
2442 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002443 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002444 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002445 }
2446}
2447
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002448#if 0
2449// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002450/* Types of text strings
2451 * Plain, b64, b64url, URI, regex, MIME Text
2452 * One function for each with options to expect plain?
2453 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002454 *
2455 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002456 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002457void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002458{
2459 QCBORItem Item;
2460 QCBORError nError;
2461
2462 nError = QCBORDecode_GetNext(pMe, &Item);
2463 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002464 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002465 return;
2466 }
2467
Laurence Lundbladec4537442020-04-14 18:53:22 -07002468 if(pLabel != NULL) {
2469 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002470 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002471 return;
2472 } else {
2473 // TODO: what about label allocation?
2474 pLabel->uLabelType = Item.uLabelType;
2475 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2476 }
2477 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002478
2479 switch(Item.uDataType) {
2480 case QCBOR_TYPE_TEXT_STRING:
2481 *pValue = Item.val.string;
2482 break;
2483
2484 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002485 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002486 }
2487}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002488#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002489
2490
Laurence Lundbladec4537442020-04-14 18:53:22 -07002491/*
2492 Options for MIME data, CBOR, positive big num, negative big num ??
2493 */
2494void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2495{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002496 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002497 // Already in error state, do nothing
2498 return;
2499 }
2500
2501 QCBORError nError;
2502 QCBORItem Item;
2503
2504 nError = QCBORDecode_GetNext(pMe, &Item);
2505 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002506 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002507 return;
2508 }
2509
2510 if(Item.uDataType == uType) {
2511 *pValue = Item.val.string;
2512 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002513 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002514 }
2515}
2516
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002517void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002518{
2519 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2520}
2521
2522
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002523void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002524{
2525 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2526}
2527
2528
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002529void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002530{
2531 // TODO: do these have to be tagged?
2532 // Probably should allow tagged or untagged, but not wrong-tagged
2533 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2534}
2535
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002536void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002537{
2538 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2539}
2540
2541
2542
Laurence Lundbladee6430642020-03-14 21:15:44 -07002543
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002544typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002545
2546
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002547// The main exponentiator that works on only positive numbers
2548static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002549{
2550 uint64_t uResult;
2551
2552 uResult = uMantissa;
2553
2554 /* This loop will run a maximum of 19 times because
2555 * UINT64_MAX < 10 ^^ 19. More than that will cause
2556 * exit with the overflow error
2557 */
2558 while(nExponent > 0) {
2559 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002560 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002561 }
2562 uResult = uResult * 10;
2563 nExponent--;
2564 }
2565
2566 while(nExponent < 0 ) {
2567 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002568 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002569 }
2570 uResult = uResult / 10;
2571 nExponent--;
2572 }
2573
2574 *puResult = uResult;
2575
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002576 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002577}
2578
2579
Laurence Lundbladee6430642020-03-14 21:15:44 -07002580/* Convert a decimal fraction to an int64_t without using
2581 floating point or math libraries. Most decimal fractions
2582 will not fit in an int64_t and this will error out with
2583 under or overflow
2584 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002585static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002586{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002587 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002588
2589 nResult = nMantissa;
2590
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002591 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002592 * INT64_MAX < 2^31. More than that will cause
2593 * exist with the overflow error
2594 */
2595 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002596 if(nResult > UINT64_MAX >> 1) {
2597 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002598 }
2599 nResult = nResult << 1;
2600 nExponent--;
2601 }
2602
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002603 while(nExponent < 0 ) {
2604 if(nResult == 0) {
2605 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2606 }
2607 nResult = nResult >> 1;
2608 nExponent--;
2609 }
2610
Laurence Lundbladee6430642020-03-14 21:15:44 -07002611 *pnResult = nResult;
2612
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002613 return QCBOR_SUCCESS;
2614}
2615
2616
2617static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2618{
2619 uint64_t uResult;
2620
2621 // Take the absolute value of the mantissa
2622 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2623
2624 // Do the exponentiation of the positive mantissa
2625 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2626 if(uReturn) {
2627 return uReturn;
2628 }
2629
2630 // Error out if too large on the plus side for an int64_t
2631 if(uResult > INT64_MAX) {
2632 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2633 }
2634
2635 // Error out if too large on the negative side for an int64_t
2636 if(uResult < (uint64_t)INT64_MAX+1) {
2637 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2638 of INT64_MIN. This assumes two's compliment representation where
2639 INT64_MIN is one increment farther from 0 than INT64_MAX.
2640 Trying to write -INT64_MIN doesn't work to get this because the
2641 compiler tries to work with an int64_t which can't represent
2642 -INT64_MIN.
2643 */
2644 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2645 }
2646
2647 // Casts are safe because of checks above
2648 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2649
2650 return QCBOR_SUCCESS;
2651}
2652
2653
2654static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2655{
2656 if(nMantissa < 0) {
2657 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2658 }
2659
2660 // Cast to unsigned is OK because of check for negative
2661 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2662 // Exponentiation is straight forward
2663 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2664}
2665
2666
2667// TODO: use this or get rid of it
2668QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2669{
2670 uint64_t uResult;
2671
2672 QCBORError uR;
2673
2674 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2675 if(uR) {
2676 return uR;
2677 }
2678
2679 if(uResult > INT64_MAX) {
2680 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2681 }
2682
2683 // Cast is OK because of check above
2684 *pnResult = (int64_t)uResult;
2685
2686 return QCBOR_SUCCESS;
2687}
2688
2689
2690
2691
2692#include <math.h>
2693/*
2694static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2695{
2696 // TODO: checkout exceptions; what is HUGE_VAL?
2697 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2698
2699 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002700 return 0;
2701}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002702*/
2703
2704
2705
2706
2707
Laurence Lundbladee6430642020-03-14 21:15:44 -07002708
2709/*
2710 A) bignum is positive
2711 A1) output is signed INT64_MAX
2712 A2) output is unsigned UINT64_MAX
2713 B) bignum is negative
2714 B1) output is signed INT64_MAX
2715 B2) output is unsigned error
2716 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002717static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002718{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002719 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002720
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002721 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002722 const uint8_t *pByte = BigNum.ptr;
2723 size_t uLen = BigNum.len;
2724 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002725 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002726 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002727 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002728 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002729 }
2730
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002731 *pResult = uResult;
2732 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002733}
2734
Laurence Lundbladec4537442020-04-14 18:53:22 -07002735
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002736#if 0
2737static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002738{
2739 double nResult;
2740
2741 nResult = 0;
2742 const uint8_t *pByte = BigNum.ptr;
2743 size_t uLen = BigNum.len;
2744 /* This will overflow and become the float value INFINITY if the number
2745 is too large to fit. No error will be logged.
2746 TODO: should an error be logged? */
2747 while(uLen--) {
2748 nResult = (nResult * 256) + *pByte;
2749 }
2750
2751 *pResult = nResult;
2752 return 0;
2753}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002754#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002755
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002756static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002757{
2758 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2759}
2760
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002761static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002762{
2763 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002764 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002765 if(n) {
2766 return n;
2767 }
2768 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2769 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002770 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002771}
2772
2773
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002774static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002775{
2776 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002777 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002778 if(n) {
2779 return n;
2780 }
2781 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2782 *pResult = -(int64_t)uResult;
2783 return 0;
2784}
2785
Laurence Lundbladec4537442020-04-14 18:53:22 -07002786// No function to convert a negative bignum to unsigned; it is an error
2787
2788
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002789#if 0
2790static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002791{
2792 int64_t nMantissa;
2793
2794 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2795 if(xx) {
2796 return xx;
2797 }
2798
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002799 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002800}
2801
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002802#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002803
2804
Laurence Lundbladee6430642020-03-14 21:15:44 -07002805
Laurence Lundbladec4537442020-04-14 18:53:22 -07002806
2807/*
2808 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2809 a big float, a decimal fraction or a big num. Conversion will be dones as
2810 expected. Some cases will error out with under or over flow.
2811 */
2812void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002813{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002814 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002815 return;
2816 }
2817
Laurence Lundbladee6430642020-03-14 21:15:44 -07002818 QCBORItem Item;
2819 QCBORError nError;
2820
2821 nError = QCBORDecode_GetNext(pMe, &Item);
2822 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002823 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002824 return;
2825 }
2826
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002827 if(pItem) {
2828 *pItem = Item;
2829 }
2830
Laurence Lundbladee6430642020-03-14 21:15:44 -07002831 switch(Item.uDataType) {
2832 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002833 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002834 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002835 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladee6430642020-03-14 21:15:44 -07002836 *pValue = (int64_t)Item.val.dfnum;
2837 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002838 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002839 }
2840 break;
2841
2842 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002843 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002844 *pValue = Item.val.int64;
2845 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002846 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002847 }
2848 break;
2849
2850 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002851 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002852 if(Item.val.uint64 < INT64_MAX) {
2853 *pValue = Item.val.int64;
2854 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002855 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002856 }
2857 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002858 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002859 }
2860 break;
2861
Laurence Lundbladec4537442020-04-14 18:53:22 -07002862 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002863 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002864 }
2865}
2866
2867/* This works for signed, unsigned and float */
2868void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2869{
2870 QCBORItem Item;
2871 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2872}
2873
2874
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002875// TODO make this inline
2876void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2877{
2878 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2879}
2880
2881
Laurence Lundbladec4537442020-04-14 18:53:22 -07002882
2883/*
2884 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2885 a big float, a decimal fraction or a big num. Conversion will be dones as
2886 expected. Some cases will error out with under or over flow.
2887 */
2888void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2889{
2890 QCBORItem Item;
2891
2892 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2893
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002894 if(pMe->uLastError == QCBOR_SUCCESS) {
2895 // The above conversion succeeded
2896 return;
2897 }
2898
2899 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2900 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002901 return;
2902 }
2903
2904 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002905
2906 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002907 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002908 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002909 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002910 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002911 }
2912 break;
2913
2914 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002915 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002916 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002917 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002918 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002919 }
2920 break;
2921
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002922#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2923 case QCBOR_TYPE_DECIMAL_FRACTION:
2924 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002925 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002926 Item.val.expAndMantissa.nExponent,
2927 pValue,
2928 &Exponentitate10UU);
2929 } else {
2930 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2931 }
2932 break;
2933
2934 case QCBOR_TYPE_BIGFLOAT:
2935 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002936 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002937 Item.val.expAndMantissa.nExponent,
2938 pValue,
2939 &Exponentitate2UU);
2940 } else {
2941 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2942 }
2943 break;
2944
2945
Laurence Lundbladee6430642020-03-14 21:15:44 -07002946 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002947 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002948 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002949 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002950 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002951 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002952 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002953 pValue,
2954 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002955 }
2956 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002957 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002958 }
2959 break;
2960
2961 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002962 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002963 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002964 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002965 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002966 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002967 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002968 pValue,
2969 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002970 }
2971 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002972 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002973 }
2974 break;
2975
2976 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002977 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002978 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002979 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002980 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002981 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002982 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002983 pValue,
2984 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002985 }
2986 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002987 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002988 }
2989 break;
2990
2991 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002992 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002993 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002994 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002995 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002996 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002997 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002998 pValue,
2999 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003000 }
3001 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003002 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003003 }
3004 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003005
3006 default:
3007 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3008#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003009 }
3010}
3011
Laurence Lundbladec4537442020-04-14 18:53:22 -07003012
3013
3014void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
3015{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003016 if(pMe->uLastError != QCBOR_SUCCESS) {
3017 return;
3018 }
3019
Laurence Lundbladec4537442020-04-14 18:53:22 -07003020 QCBORItem Item;
3021 QCBORError nError;
3022
3023 nError = QCBORDecode_GetNext(pMe, &Item);
3024 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003025 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003026 return;
3027 }
3028
3029 switch(Item.uDataType) {
3030 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003031 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003032 if(Item.val.dfnum >= 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003033 // TODO: over/underflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07003034 *pValue = (uint64_t)Item.val.dfnum;
3035 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003036 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003037 }
3038 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003039 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003040 }
3041 break;
3042
3043 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003044 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003045 if(Item.val.int64 >= 0) {
3046 *pValue = (uint64_t)Item.val.int64;
3047 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003048 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003049 }
3050 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003051 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003052 }
3053 break;
3054
3055 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003056 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003057 *pValue = Item.val.uint64;
3058 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003059 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003060 }
3061 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003062
3063 default:
3064 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003065 }
3066}
3067
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003068
3069/* This works for signed, unsigned and float */
3070void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003071{
3072 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003073 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3074}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003075
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003076
3077// TODO make this inline
3078void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3079{
3080 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3081}
3082
3083
3084
3085
3086void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3087{
3088 QCBORItem Item;
3089
3090 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3091
3092 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003093 return;
3094 }
3095
Laurence Lundbladee6430642020-03-14 21:15:44 -07003096 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003097
3098 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003099 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003100 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003101 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003102 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003103 }
3104 break;
3105
3106 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003107 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003108 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003109 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003110 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003111 }
3112 break;
3113
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003114#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3115
3116 case QCBOR_TYPE_DECIMAL_FRACTION:
3117 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003118 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003119 Item.val.expAndMantissa.nExponent,
3120 pValue,
3121 Exponentitate10UU);
3122 } else {
3123 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3124 }
3125 break;
3126
3127 case QCBOR_TYPE_BIGFLOAT:
3128 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003129 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003130 Item.val.expAndMantissa.nExponent,
3131 pValue,
3132 Exponentitate2UU);
3133 } else {
3134 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3135 }
3136 break;
3137
3138
3139
Laurence Lundbladee6430642020-03-14 21:15:44 -07003140 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003141 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003142 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003143 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003144 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003145 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003146 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003147 pValue,
3148 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003149 }
3150 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003151 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003152 }
3153 break;
3154
3155 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003156 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003157 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003158 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003159 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003160 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003161 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003162 pValue,
3163 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003164 }
3165 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003166 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003167 }
3168 break;
3169
3170 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003171 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003172 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003173 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003174 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003175 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003176 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003177 pValue,
3178 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003179 }
3180 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003181 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003182 }
3183 break;
3184
3185 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003186 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003187 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003188 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003189 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003190 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003191 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003192 pValue,
3193 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003194 }
3195 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003196 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003197 }
3198 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003199#endif
3200 default:
3201 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003202 }
3203}
3204
Laurence Lundbladec4537442020-04-14 18:53:22 -07003205
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003206
3207#if 0
Laurence Lundbladec4537442020-04-14 18:53:22 -07003208/*
3209
3210 Convert from bignums,
3211
3212 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003213void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003214{
3215 /* the same range of conversions */
3216
Laurence Lundbladec4537442020-04-14 18:53:22 -07003217 /* Conversion from bignums, decimal fractions and such will be interesting */
3218
3219 QCBORItem Item;
3220 QCBORError nError;
3221
3222 nError = QCBORDecode_GetNext(pMe, &Item);
3223 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003224 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003225 return;
3226 }
3227
Laurence Lundbladec4537442020-04-14 18:53:22 -07003228
3229 switch(Item.uDataType) {
3230 case QCBOR_TYPE_FLOAT:
3231 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3232 *pValue = Item.val.dfnum;
3233 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003234 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003235 }
3236 break;
3237
3238 case QCBOR_TYPE_INT64:
3239 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3240 // TODO: how does this work?
3241 *pValue = (double)Item.val.int64;
3242 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003243 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003244 }
3245 break;
3246
3247 case QCBOR_TYPE_UINT64:
3248 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3249 *pValue = (double)Item.val.uint64;
3250 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003251 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003252 }
3253 break;
3254
3255 case QCBOR_TYPE_DECIMAL_FRACTION:
3256 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003257 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003258 Item.val.expAndMantissa.nExponent,
3259 pValue);
3260 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003261 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003262 }
3263 break;
3264
3265 case QCBOR_TYPE_BIGFLOAT:
3266 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003267 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003268 Item.val.expAndMantissa.nExponent,
3269 pValue);
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_POSBIGNUM:
3276 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003277 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003278 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003279 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003280 }
3281 break;
3282
3283 case QCBOR_TYPE_NEGBIGNUM:
3284 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003285 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003286 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003287 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003288 }
3289 break;
3290
3291 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3292 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3293 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003294 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3295 if(!pMe->uLastError) {
3296 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003297 Item.val.expAndMantissa.nExponent,
3298 pValue);
3299 }
3300 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003301 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003302 }
3303 break;
3304
3305 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3306 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3307 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003308 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3309 if(!pMe->uLastError) {
3310 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003311 Item.val.expAndMantissa.nExponent,
3312 pValue);
3313 }
3314 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003315 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003316 }
3317 break;
3318
3319 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3320 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3321 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003322 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3323 if(!pMe->uLastError) {
3324 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003325 Item.val.expAndMantissa.nExponent,
3326 pValue);
3327 }
3328 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003329 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003330 }
3331 break;
3332
3333 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3334 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3335 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003336 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3337 if(!pMe->uLastError) {
3338 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003339 Item.val.expAndMantissa.nExponent,
3340 pValue);
3341 }
3342 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003343 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003344 }
3345 break;
3346 }
3347
3348
3349
Laurence Lundbladee6430642020-03-14 21:15:44 -07003350}
3351
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003352#endif