blob: 87d119fc008f60697722188306cbbe38e0d65e4e [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 Lundbladeee851742020-01-08 08:37:05 -0800115inline static int
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700116// TODO: make this bool
117// TODO: add Map as array?
Laurence Lundbladeee851742020-01-08 08:37:05 -0800118IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119{
120 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
121}
122
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700123inline static bool
124DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700126 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
127 return true;
128 } else {
129 return false;
130 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700131}
132
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700133// Determine if at the end of a map or array, taking into
134// account map mode. If this returns true, it is OK
135// to get another item.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700136inline static bool
137DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
138{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700139 if(DecodeNesting_IsAtTop(pNesting)){
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700140 // Always at end if at the top level of nesting
141 return true;
142 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143
144 if(pNesting->pCurrent->uMapMode) {
145 if(pNesting->pCurrent->uCount == 0) {
146 // In map mode and consumed all items, so it is the end
147 return true;
148 } else {
149 // In map mode, all items not consumed, so it is NOT the end
150 return false;
151 }
152 } else {
153 // Not in map mode, and not at top level so it NOT the end.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700154 return false;
155 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700156}
157
158
Laurence Lundbladeee851742020-01-08 08:37:05 -0800159inline static int
160DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700161{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700162 return pNesting->pCurrent->uCount == UINT16_MAX;
163}
164
Laurence Lundbladeee851742020-01-08 08:37:05 -0800165inline static uint8_t
166DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800167{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800168 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700169 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800170 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800171}
172
Laurence Lundbladeee851742020-01-08 08:37:05 -0800173inline static int
174DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700176 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700177 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800179
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700180 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
181}
182
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800184inline static QCBORError
185DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700186{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800187 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700188 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800189 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192 // breaks can only occur when the map/array is indefinite length
193 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
194 return QCBOR_ERR_BAD_BREAK;
195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800196
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800197 // if all OK, the break reduces the level of nesting
198 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800199
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800200 return QCBOR_SUCCESS;
201}
202
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700203// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700204/* Decrements the map/array counter if possible. If decrement
205 closed out a map or array, then level up in nesting and decrement
206 again, until, the top is reached or the end of a map mode is reached
207 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800208inline static void
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700209DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting, bool bExitingMapMode)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800210{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700211 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700212 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800213
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800214 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700215 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800216 pNesting->pCurrent->uCount--;
217 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700218
219 if(pNesting->pCurrent->uCount != 0) {
220 // Did not close out an array or map, so nothing further
221 break;
222 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700223
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700224 if(pNesting->pCurrent->uMapMode && !bExitingMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700225 // In map mode the level-up must be done explicitly
226 break;
227 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700228
229 // Closed out an array or map so level up
230 pNesting->pCurrent--;
231
232 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700233 }
234}
235
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800236// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800237inline static QCBORError
238DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700239{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700240 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800241
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800242 if(pItem->val.uCount == 0) {
243 // Nothing to do for empty definite lenth arrays. They are just are
244 // effectively the same as an item that is not a map or array
245 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530246 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800247 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800248
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800249 // Error out if arrays is too long to handle
250 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
252 goto Done;
253 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800254
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800255 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
257 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
258 goto Done;
259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800260
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800261 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700262 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800263
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800264 // Record a few details for this nesting level
265 pNesting->pCurrent->uMajorType = pItem->uDataType;
266 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700267 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800268
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700269Done:
270 return nReturn;;
271}
272
Laurence Lundbladeee851742020-01-08 08:37:05 -0800273inline static void
274DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275{
276 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
277}
278
279
280
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700281/*
282 This list of built-in tags. Only add tags here that are
283 clearly established and useful. Once a tag is added here
284 it can't be taken out as that would break backwards compatibility.
285 There are only 48 slots available forever.
286 */
287static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800288 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
289 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
290 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
291 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
292 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
293 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700294 CBOR_TAG_COSE_ENCRYPTO,
295 CBOR_TAG_COSE_MAC0,
296 CBOR_TAG_COSE_SIGN1,
297 CBOR_TAG_ENC_AS_B64URL,
298 CBOR_TAG_ENC_AS_B64,
299 CBOR_TAG_ENC_AS_B16,
300 CBOR_TAG_CBOR,
301 CBOR_TAG_URI,
302 CBOR_TAG_B64URL,
303 CBOR_TAG_B64,
304 CBOR_TAG_REGEX,
305 CBOR_TAG_MIME,
306 CBOR_TAG_BIN_UUID,
307 CBOR_TAG_CWT,
308 CBOR_TAG_ENCRYPT,
309 CBOR_TAG_MAC,
310 CBOR_TAG_SIGN,
311 CBOR_TAG_GEO_COORD,
312 CBOR_TAG_CBOR_MAGIC
313};
314
315// This is used in a bit of cleverness in GetNext_TaggedItem() to
316// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800317// these types. This will break if the first six items in
318// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
319// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
320#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
321#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
322#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
323#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
324#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
325#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700326
Laurence Lundblade59289e52019-12-30 13:44:37 -0800327#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
328 QCBOR_TAGFLAG_DATE_EPOCH |\
329 QCBOR_TAGFLAG_POS_BIGNUM |\
330 QCBOR_TAGFLAG_NEG_BIGNUM |\
331 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
332 QCBOR_TAGFLAG_BIGFLOAT)
333
334#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
335 QCBOR_TAGFLAG_DATE_EPOCH |\
336 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700337 QCBOR_TAGFLAG_NEG_BIGNUM)
338
339#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
340#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
341#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
342
343static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
344{
345 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800346 /*
347 This is a cross-check to make sure the above array doesn't
348 accidentally get made too big. In normal conditions the above
349 test should optimize out as all the values are known at compile
350 time.
351 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700352 return -1;
353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800354
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700355 if(uTag > UINT16_MAX) {
356 // This tag map works only on 16-bit tags
357 return -1;
358 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800359
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700360 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
361 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
362 return nTagBitIndex;
363 }
364 }
365 return -1; // Indicates no match
366}
367
368static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
369{
370 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
371 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
372 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
373 }
374 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800375
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700376 return -1; // Indicates no match
377}
378
379/*
380 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800381
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700382 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800383 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700384 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800385static QCBORError
386TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
387 uint64_t uTag,
388 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700389{
390 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
391 if(nTagBitIndex >= 0) {
392 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
393 *puTagBitIndex = (uint8_t)nTagBitIndex;
394 return QCBOR_SUCCESS;
395 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800396
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700397 if(pCallerConfiguredTagMap) {
398 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
399 return QCBOR_ERR_TOO_MANY_TAGS;
400 }
401 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
402 if(nTagBitIndex >= 0) {
403 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
404
405 *puTagBitIndex = (uint8_t)nTagBitIndex;
406 return QCBOR_SUCCESS;
407 }
408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800409
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700410 return QCBOR_ERR_BAD_OPT_TAG;
411}
412
413
414
Laurence Lundbladeee851742020-01-08 08:37:05 -0800415/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800416 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
417
418 The following four functions are pretty wrappers for invocation of
419 the string allocator supplied by the caller.
420
Laurence Lundbladeee851742020-01-08 08:37:05 -0800421 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800422
Laurence Lundbladeee851742020-01-08 08:37:05 -0800423static inline void
424StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800425{
426 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
427}
428
Laurence Lundbladeee851742020-01-08 08:37:05 -0800429// StringAllocator_Reallocate called with pMem NULL is
430// equal to StringAllocator_Allocate()
431static inline UsefulBuf
432StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
433 void *pMem,
434 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800435{
436 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
437}
438
Laurence Lundbladeee851742020-01-08 08:37:05 -0800439static inline UsefulBuf
440StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800441{
442 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
443}
444
Laurence Lundbladeee851742020-01-08 08:37:05 -0800445static inline void
446StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800447{
448 if(pMe->pfAllocator) {
449 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
450 }
451}
452
453
454
Laurence Lundbladeee851742020-01-08 08:37:05 -0800455/*===========================================================================
456 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700457
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800458 See qcbor/qcbor_decode.h for definition of the object
459 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800460 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700461/*
462 Public function, see header file
463 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464void QCBORDecode_Init(QCBORDecodeContext *me,
465 UsefulBufC EncodedCBOR,
466 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467{
468 memset(me, 0, sizeof(QCBORDecodeContext));
469 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800470 // Don't bother with error check on decode mode. If a bad value is
471 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700472 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700473 DecodeNesting_Init(&(me->nesting));
474}
475
476
477/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700478 Public function, see header file
479 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800480void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
481 QCBORStringAllocate pfAllocateFunction,
482 void *pAllocateContext,
483 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700484{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
486 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
487 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700488}
489
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800490
491/*
492 Public function, see header file
493 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800494void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
495 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700496{
497 me->pCallerConfiguredTagList = pTagList;
498}
499
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700500
501/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800502 This decodes the fundamental part of a CBOR data item, the type and
503 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800504
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700505 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800506
Laurence Lundbladeee851742020-01-08 08:37:05 -0800507 This does the network->host byte order conversion. The conversion
508 here also results in the conversion for floats in addition to that
509 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800510
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700511 This returns:
512 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800514 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515 tags and floats and length for strings and arrays
516
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800517 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800519
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800520 The int type is preferred to uint8_t for some variables as this
521 avoids integer promotions, can reduce code size and makes
522 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700523 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800524inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
525 int *pnMajorType,
526 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800527 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700529 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800532 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800533
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800535 const int nTmpMajorType = nInitialByte >> 5;
536 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800538 // Where the number or argument accumulates
539 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800540
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800541 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542 // Need to get 1,2,4 or 8 additional argument bytes Map
543 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800544 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800545
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800546 // Loop getting all the bytes in the argument
547 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800548 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800549 // This shift and add gives the endian conversion
550 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
551 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800552 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800553 // The reserved and thus-far unused additional info values
554 nReturn = QCBOR_ERR_UNSUPPORTED;
555 goto Done;
556 } else {
557 // Less than 24, additional info is argument or 31, an indefinite length
558 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800559 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700560 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800561
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562 if(UsefulInputBuf_GetError(pUInBuf)) {
563 nReturn = QCBOR_ERR_HIT_END;
564 goto Done;
565 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800566
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567 // All successful if we got here.
568 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800569 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800570 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800571 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800572
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700573Done:
574 return nReturn;
575}
576
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800577
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579 CBOR doesn't explicitly specify two's compliment for integers but all
580 CPUs use it these days and the test vectors in the RFC are so. All
581 integers in the CBOR structure are positive and the major type
582 indicates positive or negative. CBOR can express positive integers
583 up to 2^x - 1 where x is the number of bits and negative integers
584 down to 2^x. Note that negative numbers can be one more away from
585 zero than positive. Stdint, as far as I can tell, uses two's
586 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800587
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 used carefully here, and in particular why it isn't used in the interface.
590 Also see
591 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
592
593 Int is used for values that need less than 16-bits and would be subject
594 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596inline static QCBORError
597DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700599 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700601 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
602 if (uNumber <= INT64_MAX) {
603 pDecodedItem->val.int64 = (int64_t)uNumber;
604 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700606 } else {
607 pDecodedItem->val.uint64 = uNumber;
608 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 }
611 } else {
612 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 // CBOR's representation of negative numbers lines up with the
614 // two-compliment representation. A negative integer has one
615 // more in range than a positive integer. INT64_MIN is
616 // equal to (-INT64_MAX) - 1.
617 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 } else {
621 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000622 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 nReturn = QCBOR_ERR_INT_OVERFLOW;
624 }
625 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 return nReturn;
628}
629
630// Make sure #define value line up as DecodeSimple counts on this.
631#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
632#error QCBOR_TYPE_FALSE macro value wrong
633#endif
634
635#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
636#error QCBOR_TYPE_TRUE macro value wrong
637#endif
638
639#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
640#error QCBOR_TYPE_NULL macro value wrong
641#endif
642
643#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
644#error QCBOR_TYPE_UNDEF macro value wrong
645#endif
646
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700647#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
648#error QCBOR_TYPE_BREAK macro value wrong
649#endif
650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
652#error QCBOR_TYPE_DOUBLE macro value wrong
653#endif
654
655#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
656#error QCBOR_TYPE_FLOAT macro value wrong
657#endif
658
659/*
660 Decode true, false, floats, break...
661 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800662inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700665 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundbladeee851742020-01-08 08:37:05 -0800667 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 // above make sure uAdditionalInfo values line up with uDataType values.
669 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
670 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800672 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800673 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
674 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800675
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700676 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700677 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
678 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700679 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700680 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700681 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
682 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700683 break;
684 case DOUBLE_PREC_FLOAT:
685 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700686 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700687 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 case CBOR_SIMPLEV_FALSE: // 20
690 case CBOR_SIMPLEV_TRUE: // 21
691 case CBOR_SIMPLEV_NULL: // 22
692 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700693 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696 case CBOR_SIMPLEV_ONEBYTE: // 24
697 if(uNumber <= CBOR_SIMPLE_BREAK) {
698 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700699 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700 goto Done;
701 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800702 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700703 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700705 default: // 0-19
706 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800707 /*
708 DecodeTypeAndNumber will make uNumber equal to
709 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
710 safe because the 2, 4 and 8 byte lengths of uNumber are in
711 the double/float cases above
712 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 pDecodedItem->val.uSimple = (uint8_t)uNumber;
714 break;
715 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717Done:
718 return nReturn;
719}
720
721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530723 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800725inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
726 int nMajorType,
727 uint64_t uStrLen,
728 UsefulInputBuf *pUInBuf,
729 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700730{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700731 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800732
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
734 // This check makes the casts to size_t below safe.
735
736 // 4 bytes less than the largest sizeof() so this can be tested by
737 // putting a SIZE_MAX length in the CBOR test input (no one will
738 // care the limit on strings is 4 bytes shorter).
739 if(uStrLen > SIZE_MAX-4) {
740 nReturn = QCBOR_ERR_STRING_TOO_LONG;
741 goto Done;
742 }
743
744 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530745 if(UsefulBuf_IsNULLC(Bytes)) {
746 // Failed to get the bytes for this string item
747 nReturn = QCBOR_ERR_HIT_END;
748 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530750
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800751 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530752 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530754 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700755 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530756 goto Done;
757 }
758 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800759 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530760 } else {
761 // Normal case with no string allocator
762 pDecodedItem->val.string = Bytes;
763 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800764 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800765 // Cast because ternary operator causes promotion to integer
766 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
767 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530769Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 return nReturn;
771}
772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800774
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700775
776
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777
778
Laurence Lundbladeee851742020-01-08 08:37:05 -0800779// Make sure the constants align as this is assumed by
780// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
782#error QCBOR_TYPE_ARRAY value not lined up with major type
783#endif
784#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
785#error QCBOR_TYPE_MAP value not lined up with major type
786#endif
787
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 This gets a single data item and decodes it including preceding
790 optional tagging. This does not deal with arrays and maps and nesting
791 except to decode the data item introducing them. Arrays and maps are
792 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundbladeee851742020-01-08 08:37:05 -0800794 Errors detected here include: an array that is too long to decode,
795 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800797static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
798 QCBORItem *pDecodedItem,
799 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700800{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700801 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundbladeee851742020-01-08 08:37:05 -0800803 /*
804 Get the major type and the number. Number could be length of more
805 bytes or the value depending on the major type nAdditionalInfo is
806 an encoding of the length of the uNumber and is needed to decode
807 floats and doubles
808 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700810 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800811 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700813 memset(pDecodedItem, 0, sizeof(QCBORItem));
814
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800815 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800816
Laurence Lundbladeee851742020-01-08 08:37:05 -0800817 // Error out here if we got into trouble on the type and number. The
818 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700819 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700820 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeee851742020-01-08 08:37:05 -0800823 // At this point the major type and the value are valid. We've got
824 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800825 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700826 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
827 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800828 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700829 nReturn = QCBOR_ERR_BAD_INT;
830 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800831 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700832 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800834
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700835 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
836 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800837 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
838 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
839 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
840 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530841 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800843 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 }
845 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
848 case CBOR_MAJOR_TYPE_MAP: // Major type 5
849 // Record the number of items in the array or map
850 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
851 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
852 goto Done;
853 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800854 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530855 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700856 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800857 // type conversion OK because of check above
858 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700859 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800860 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800861 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
862 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800864
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800866 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700867 nReturn = QCBOR_ERR_BAD_INT;
868 } else {
869 pDecodedItem->val.uTagV = uNumber;
870 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
871 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700872 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800873
Laurence Lundbladeee851742020-01-08 08:37:05 -0800874 case CBOR_MAJOR_TYPE_SIMPLE:
875 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700877 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800878
Laurence Lundbladeee851742020-01-08 08:37:05 -0800879 default:
880 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 nReturn = QCBOR_ERR_UNSUPPORTED;
882 break;
883 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800884
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885Done:
886 return nReturn;
887}
888
889
890
891/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800892 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800893 individual chunk items together into one QCBORItem using the string
894 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530896 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800898static inline QCBORError
899GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700900{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700901 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700902
903 // Get pointer to string allocator. First use is to pass it to
904 // GetNext_Item() when option is set to allocate for *every* string.
905 // Second use here is to allocate space to coallese indefinite
906 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800907 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
908 &(me->StringAllocator) :
909 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800910
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700911 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800912 nReturn = GetNext_Item(&(me->InBuf),
913 pDecodedItem,
914 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 if(nReturn) {
916 goto Done;
917 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800918
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700919 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530920 // code in this function from here down can be eliminated. Run tests, except
921 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800923 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700924 const uint8_t uStringType = pDecodedItem->uDataType;
925 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700926 goto Done; // no need to do any work here on non-string types
927 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800929 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530930 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800931 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700932 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800933
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530934 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800935 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
937 goto Done;
938 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700940 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700941 UsefulBufC FullString = NULLUsefulBufC;
942
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700943 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700944 // Get item for next chunk
945 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700946 // NULL string allocator passed here. Do not need to allocate
947 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800948 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700949 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700950 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530953 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700954 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800955 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530957 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958 break;
959 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700961 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530962 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700963 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(StringChunkItem.uDataType != uStringType ||
965 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700966 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 break;
968 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530970 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800971 // The first time throurgh FullString.ptr is NULL and this is
972 // equivalent to StringAllocator_Allocate()
973 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
974 UNCONST_POINTER(FullString.ptr),
975 FullString.len + StringChunkItem.val.string.len);
976
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530978 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700979 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700980 break;
981 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700983 // Copy new string chunk at the end of string so far.
984 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800987 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
988 // Getting the item failed, clean up the allocated memory
989 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700992Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 return nReturn;
994}
995
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700996
997/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800998 Gets all optional tag data items preceding a data item that is not an
999 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001000 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001static QCBORError
1002GetNext_TaggedItem(QCBORDecodeContext *me,
1003 QCBORItem *pDecodedItem,
1004 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001005{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001006 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001007 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001008 uint64_t uTagBits = 0;
1009 if(pTags) {
1010 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001012
Laurence Lundblade59289e52019-12-30 13:44:37 -08001013 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001014 for(;;) {
1015 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001016 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001017 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001020 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1021 // Successful exit from loop; maybe got some tags, maybe not
1022 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001023 break;
1024 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001026 uint8_t uTagBitIndex;
1027 // Tag was mapped, tag was not mapped, error with tag list
1028 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001029
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001030 case QCBOR_SUCCESS:
1031 // Successfully mapped the tag
1032 uTagBits |= 0x01ULL << uTagBitIndex;
1033 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001035 case QCBOR_ERR_BAD_OPT_TAG:
1036 // Tag is not recognized. Do nothing
1037 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001038
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001039 default:
1040 // Error Condition
1041 goto Done;
1042 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001044 if(pTags) {
1045 // Caller wants all tags recorded in the provided buffer
1046 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1047 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1048 goto Done;
1049 }
1050 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1051 pTags->uNumUsed++;
1052 }
1053 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001055Done:
1056 return nReturn;
1057}
1058
1059
1060/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001061 This layer takes care of map entries. It combines the label and data
1062 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001063 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001064static inline QCBORError
1065GetNext_MapEntry(QCBORDecodeContext *me,
1066 QCBORItem *pDecodedItem,
1067 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001068{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001069 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001070 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001071 if(nReturn)
1072 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001074 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001075 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001076 goto Done;
1077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001079 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1080 // In a map and caller wants maps decoded, not treated as arrays
1081
1082 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1083 // If in a map and the right decoding mode, get the label
1084
Laurence Lundbladeee851742020-01-08 08:37:05 -08001085 // Save label in pDecodedItem and get the next which will
1086 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001087 QCBORItem LabelItem = *pDecodedItem;
1088 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1089 if(nReturn)
1090 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001091
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301092 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001093
1094 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1095 // strings are always good labels
1096 pDecodedItem->label.string = LabelItem.val.string;
1097 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1098 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001099 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001100 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1101 goto Done;
1102 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1103 pDecodedItem->label.int64 = LabelItem.val.int64;
1104 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1105 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1106 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1107 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1108 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1109 pDecodedItem->label.string = LabelItem.val.string;
1110 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1111 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1112 } else {
1113 // label is not an int or a string. It is an arrray
1114 // or a float or such and this implementation doesn't handle that.
1115 // Also, tags on labels are ignored.
1116 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1117 goto Done;
1118 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001119 }
1120 } else {
1121 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001122 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1123 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1124 goto Done;
1125 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001126 // Decoding a map as an array
1127 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001128 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1129 // Cast is needed because of integer promotion
1130 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 }
1132 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001134Done:
1135 return nReturn;
1136}
1137
1138
1139/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001140 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001141 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001143QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1144 QCBORItem *pDecodedItem,
1145 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001147 // Stack ptr/int: 2, QCBORItem : 64
1148
Laurence Lundblade30816f22018-11-10 13:40:22 +07001149 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001150
Laurence Lundblade1341c592020-04-11 14:19:05 -07001151 // Check if there are an TODO: incomplete comment
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001152 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001153 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1154 goto Done;
1155 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001156
1157 // This is to handle map and array mode
1158 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1159 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1160 goto Done;
1161 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001162
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001163 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001164 if(nReturn) {
1165 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001166 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301167
1168 // Break ending arrays/maps are always processed at the end of this function.
1169 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301170 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301171 nReturn = QCBOR_ERR_BAD_BREAK;
1172 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301173 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundblade6de37062018-10-15 12:22:42 +05301175 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301176 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301177 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade6de37062018-10-15 12:22:42 +05301179 // Process the item just received for descent or decrement, and
1180 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001181 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001182 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001183 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001184 // Maps and arrays do count in as items in the map/array that encloses
1185 // them so a decrement needs to be done for them too, but that is done
1186 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001187 // are opened with the exception of an empty map or array.
1188 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001189 DecodeNesting_DecrementCount(&(me->nesting), false);
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001190 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001191 } else {
1192 // Decrement the count of items in the enclosing map/array
1193 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301194 // triggers a decrement in the map/array above that and
1195 // an ascend in nesting level.
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001196 DecodeNesting_DecrementCount(&(me->nesting), false);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001197 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301198 if(nReturn) {
1199 goto Done;
1200 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundblade6de37062018-10-15 12:22:42 +05301202 // For indefinite length maps/arrays, looking at any and
1203 // all breaks that might terminate them. The equivalent
1204 // for definite length maps/arrays happens in
1205 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001206 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301207 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1208 // Peek forward one item to see if it is a break.
1209 QCBORItem Peek;
1210 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1211 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1212 if(nReturn) {
1213 goto Done;
1214 }
1215 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1216 // It is not a break, rewind so it can be processed normally.
1217 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1218 break;
1219 }
1220 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301221 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301222 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1223 if(nReturn) {
1224 // break occured outside of an indefinite length array/map
1225 goto Done;
1226 }
1227 }
1228 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001229
Laurence Lundblade6de37062018-10-15 12:22:42 +05301230 // Tell the caller what level is next. This tells them what maps/arrays
1231 // were closed out and makes it possible for them to reconstruct
1232 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001233 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1234 // At end of a map / array in map mode, so next nest is 0 to
1235 // indicate this end.
1236 pDecodedItem->uNextNestLevel = 0;
1237 } else {
1238 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1239 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001240
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001241Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001242 if(nReturn != QCBOR_SUCCESS) {
1243 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1244 memset(pDecodedItem, 0, sizeof(QCBORItem));
1245 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246 return nReturn;
1247}
1248
1249
Laurence Lundblade59289e52019-12-30 13:44:37 -08001250/*
1251 Mostly just assign the right data type for the date string.
1252 */
1253inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1254{
1255 // Stack Use: UsefulBuf 1 16
1256 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1257 return QCBOR_ERR_BAD_OPT_TAG;
1258 }
1259
1260 const UsefulBufC Temp = pDecodedItem->val.string;
1261 pDecodedItem->val.dateString = Temp;
1262 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1263 return QCBOR_SUCCESS;
1264}
1265
1266
1267/*
1268 Mostly just assign the right data type for the bignum.
1269 */
1270inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1271{
1272 // Stack Use: UsefulBuf 1 -- 16
1273 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1274 return QCBOR_ERR_BAD_OPT_TAG;
1275 }
1276 const UsefulBufC Temp = pDecodedItem->val.string;
1277 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001278 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001279 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1280 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001281 return QCBOR_SUCCESS;
1282}
1283
1284
1285/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001286 The epoch formatted date. Turns lots of different forms of encoding
1287 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001288 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001289static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001290{
1291 // Stack usage: 1
1292 QCBORError nReturn = QCBOR_SUCCESS;
1293
1294 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1295
1296 switch (pDecodedItem->uDataType) {
1297
1298 case QCBOR_TYPE_INT64:
1299 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1300 break;
1301
1302 case QCBOR_TYPE_UINT64:
1303 if(pDecodedItem->val.uint64 > INT64_MAX) {
1304 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1305 goto Done;
1306 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001307 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001308 break;
1309
1310 case QCBOR_TYPE_DOUBLE:
1311 {
1312 // This comparison needs to be done as a float before
1313 // conversion to an int64_t to be able to detect doubles
1314 // that are too large to fit into an int64_t. A double
1315 // has 52 bits of preceision. An int64_t has 63. Casting
1316 // INT64_MAX to a double actually causes a round up which
1317 // is bad and wrong for the comparison because it will
1318 // allow conversion of doubles that can't fit into a
1319 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1320 // the cutoff point as if that rounds up in conversion to
1321 // double it will still be less than INT64_MAX. 0x7ff is
1322 // picked because it has 11 bits set.
1323 //
1324 // INT64_MAX seconds is on the order of 10 billion years,
1325 // and the earth is less than 5 billion years old, so for
1326 // most uses this conversion error won't occur even though
1327 // doubles can go much larger.
1328 //
1329 // Without the 0x7ff there is a ~30 minute range of time
1330 // values 10 billion years in the past and in the future
1331 // where this this code would go wrong.
1332 const double d = pDecodedItem->val.dfnum;
1333 if(d > (double)(INT64_MAX - 0x7ff)) {
1334 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1335 goto Done;
1336 }
1337 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1338 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1339 }
1340 break;
1341
1342 default:
1343 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1344 goto Done;
1345 }
1346 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1347
1348Done:
1349 return nReturn;
1350}
1351
1352
1353#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1354/*
1355 Decode decimal fractions and big floats.
1356
1357 When called pDecodedItem must be the array that is tagged as a big
1358 float or decimal fraction, the array that has the two members, the
1359 exponent and mantissa.
1360
1361 This will fetch and decode the exponent and mantissa and put the
1362 result back into pDecodedItem.
1363 */
1364inline static QCBORError
1365QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1366{
1367 QCBORError nReturn;
1368
1369 // --- Make sure it is an array; track nesting level of members ---
1370 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1371 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1372 goto Done;
1373 }
1374
1375 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001376 // definite length arrays, but not for indefnite. Instead remember
1377 // the nesting level the two integers must be at, which is one
1378 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001379 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1380
1381 // --- Is it a decimal fraction or a bigfloat? ---
1382 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1383 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1384
1385 // --- Get the exponent ---
1386 QCBORItem exponentItem;
1387 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1388 if(nReturn != QCBOR_SUCCESS) {
1389 goto Done;
1390 }
1391 if(exponentItem.uNestingLevel != nNestLevel) {
1392 // Array is empty or a map/array encountered when expecting an int
1393 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1394 goto Done;
1395 }
1396 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1397 // Data arriving as an unsigned int < INT64_MAX has been converted
1398 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1399 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1400 // will be too large for this to handle and thus an error that will
1401 // get handled in the next else.
1402 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1403 } else {
1404 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1405 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1406 goto Done;
1407 }
1408
1409 // --- Get the mantissa ---
1410 QCBORItem mantissaItem;
1411 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1412 if(nReturn != QCBOR_SUCCESS) {
1413 goto Done;
1414 }
1415 if(mantissaItem.uNestingLevel != nNestLevel) {
1416 // Mantissa missing or map/array encountered when expecting number
1417 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1418 goto Done;
1419 }
1420 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1421 // Data arriving as an unsigned int < INT64_MAX has been converted
1422 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1423 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1424 // will be too large for this to handle and thus an error that
1425 // will get handled in an else below.
1426 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1427 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1428 // Got a good big num mantissa
1429 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1430 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001431 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1432 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1433 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001434 } else {
1435 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1436 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1437 goto Done;
1438 }
1439
1440 // --- Check that array only has the two numbers ---
1441 if(mantissaItem.uNextNestLevel == nNestLevel) {
1442 // Extra items in the decimal fraction / big num
1443 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1444 goto Done;
1445 }
1446
1447Done:
1448
1449 return nReturn;
1450}
1451#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1452
1453
1454/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001455 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001456 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001457QCBORError
1458QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1459 QCBORItem *pDecodedItem,
1460 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001461{
1462 QCBORError nReturn;
1463
1464 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1465 if(nReturn != QCBOR_SUCCESS) {
1466 goto Done;
1467 }
1468
1469#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1470#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1471#else
1472#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1473#endif
1474
1475 // Only pay attention to tags this code knows how to decode.
1476 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1477 case 0:
1478 // No tags at all or none we know about. Nothing to do.
1479 // This is the pass-through path of this function
1480 // that will mostly be taken when decoding any item.
1481 break;
1482
1483 case QCBOR_TAGFLAG_DATE_STRING:
1484 nReturn = DecodeDateString(pDecodedItem);
1485 break;
1486
1487 case QCBOR_TAGFLAG_DATE_EPOCH:
1488 nReturn = DecodeDateEpoch(pDecodedItem);
1489 break;
1490
1491 case QCBOR_TAGFLAG_POS_BIGNUM:
1492 case QCBOR_TAGFLAG_NEG_BIGNUM:
1493 nReturn = DecodeBigNum(pDecodedItem);
1494 break;
1495
1496#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1497 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1498 case QCBOR_TAGFLAG_BIGFLOAT:
1499 // For aggregate tagged types, what goes into pTags is only collected
1500 // from the surrounding data item, not the contents, so pTags is not
1501 // passed on here.
1502
1503 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1504 break;
1505#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1506
1507 default:
1508 // Encountering some mixed-up CBOR like something that
1509 // is tagged as both a string and integer date.
1510 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1511 }
1512
1513Done:
1514 if(nReturn != QCBOR_SUCCESS) {
1515 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1516 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1517 }
1518 return nReturn;
1519}
1520
1521
1522/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001523 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001524 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001525QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001526{
1527 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1528}
1529
1530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001531/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301532 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301533 next one down. If a layer has no work to do for a particular item
1534 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade59289e52019-12-30 13:44:37 -08001536 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1537 tagged data items, turning them into the local C representation.
1538 For the most simple it is just associating a QCBOR_TYPE with the data. For
1539 the complex ones that an aggregate of data items, there is some further
1540 decoding and a little bit of recursion.
1541
1542 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301543 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301544 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001545 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001546
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301547 - GetNext_MapEntry -- This handles the combining of two
1548 items, the label and the data, that make up a map entry.
1549 It only does work on maps. It combines the label and data
1550 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001551
Laurence Lundblade59289e52019-12-30 13:44:37 -08001552 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1553 tags into bit flags associated with the data item. No actual decoding
1554 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001555
Laurence Lundblade59289e52019-12-30 13:44:37 -08001556 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301557 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301558 string allocater to create contiguous space for the item. It
1559 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundblade59289e52019-12-30 13:44:37 -08001561 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1562 atomic data item has a "major type", an integer "argument" and optionally
1563 some content. For text and byte strings, the content is the bytes
1564 that make up the string. These are the smallest data items that are
1565 considered to be well-formed. The content may also be other data items in
1566 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001567
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001568 Roughly this takes 300 bytes of stack for vars. Need to
1569 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001570
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301571 */
1572
1573
1574/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001575 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001576 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001577int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1578 const QCBORItem *pItem,
1579 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001580{
1581 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001582
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001583 uint8_t uTagBitIndex;
1584 // Do not care about errors in pCallerConfiguredTagMap here. They are
1585 // caught during GetNext() before this is called.
1586 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1587 return 0;
1588 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001589
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001590 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1591 return (uTagBit & pItem->uTagBits) != 0;
1592}
1593
1594
1595/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001596 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001597 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001598QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001599{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001600 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001601
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001602 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001603 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001604 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1605 goto Done;
1606 }
1607
1608 // Error out if not all the bytes are consumed
1609 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1610 nReturn = QCBOR_ERR_EXTRA_BYTES;
1611 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001612
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001613Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301614 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001615 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001616 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001617
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001618 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001619}
1620
1621
1622
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001623/*
1624
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001625Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001626
Laurence Lundbladeee851742020-01-08 08:37:05 -08001627 - Hit end of input before it was expected while decoding type and
1628 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001629
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001630 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001631
Laurence Lundbladeee851742020-01-08 08:37:05 -08001632 - Hit end of input while decoding a text or byte string
1633 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001634
Laurence Lundbladeee851742020-01-08 08:37:05 -08001635 - Encountered conflicting tags -- e.g., an item is tagged both a date
1636 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001637
Laurence Lundbladeee851742020-01-08 08:37:05 -08001638 - Encontered an array or mapp that has too many items
1639 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001640
Laurence Lundbladeee851742020-01-08 08:37:05 -08001641 - Encountered array/map nesting that is too deep
1642 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001643
Laurence Lundbladeee851742020-01-08 08:37:05 -08001644 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1645 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001646
Laurence Lundbladeee851742020-01-08 08:37:05 -08001647 - The type of a map label is not a string or int
1648 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001650 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001652 */
1653
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001654
1655
Laurence Lundbladef6531662018-12-04 10:42:22 +09001656
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001657/* ===========================================================================
1658 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001659
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001660 This implements a simple sting allocator for indefinite length
1661 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1662 implements the function type QCBORStringAllocate and allows easy
1663 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001664
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001665 This particular allocator is built-in for convenience. The caller
1666 can implement their own. All of this following code will get
1667 dead-stripped if QCBORDecode_SetMemPool() is not called.
1668
1669 This is a very primitive memory allocator. It does not track
1670 individual allocations, only a high-water mark. A free or
1671 reallocation must be of the last chunk allocated.
1672
1673 The size of the pool and offset to free memory are packed into the
1674 first 8 bytes of the memory pool so we don't have to keep them in
1675 the decode context. Since the address of the pool may not be
1676 aligned, they have to be packed and unpacked as if they were
1677 serialized data of the wire or such.
1678
1679 The sizes packed in are uint32_t to be the same on all CPU types
1680 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001681 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001682
1683
Laurence Lundbladeee851742020-01-08 08:37:05 -08001684static inline int
1685MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001686{
1687 // Use of UsefulInputBuf is overkill, but it is convenient.
1688 UsefulInputBuf UIB;
1689
Laurence Lundbladeee851742020-01-08 08:37:05 -08001690 // Just assume the size here. It was checked during SetUp so
1691 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001692 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1693 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1694 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1695 return UsefulInputBuf_GetError(&UIB);
1696}
1697
1698
Laurence Lundbladeee851742020-01-08 08:37:05 -08001699static inline int
1700MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001701{
1702 // Use of UsefulOutBuf is overkill, but convenient. The
1703 // length check performed here is useful.
1704 UsefulOutBuf UOB;
1705
1706 UsefulOutBuf_Init(&UOB, Pool);
1707 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1708 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1709 return UsefulOutBuf_GetError(&UOB);
1710}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001711
1712
1713/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001714 Internal function for an allocation, reallocation free and destuct.
1715
1716 Having only one function rather than one each per mode saves space in
1717 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001718
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001719 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1720 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001721static UsefulBuf
1722MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001723{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001724 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001725
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001726 uint32_t uPoolSize;
1727 uint32_t uFreeOffset;
1728
1729 if(uNewSize > UINT32_MAX) {
1730 // This allocator is only good up to 4GB. This check should
1731 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1732 goto Done;
1733 }
1734 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1735
1736 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1737 goto Done;
1738 }
1739
1740 if(uNewSize) {
1741 if(pMem) {
1742 // REALLOCATION MODE
1743 // Calculate pointer to the end of the memory pool. It is
1744 // assumed that pPool + uPoolSize won't wrap around by
1745 // assuming the caller won't pass a pool buffer in that is
1746 // not in legitimate memory space.
1747 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1748
1749 // Check that the pointer for reallocation is in the range of the
1750 // pool. This also makes sure that pointer math further down
1751 // doesn't wrap under or over.
1752 if(pMem >= pPool && pMem < pPoolEnd) {
1753 // Offset to start of chunk for reallocation. This won't
1754 // wrap under because of check that pMem >= pPool. Cast
1755 // is safe because the pool is always less than UINT32_MAX
1756 // because of check in QCBORDecode_SetMemPool().
1757 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1758
1759 // Check to see if the allocation will fit. uPoolSize -
1760 // uMemOffset will not wrap under because of check that
1761 // pMem is in the range of the uPoolSize by check above.
1762 if(uNewSize <= uPoolSize - uMemOffset) {
1763 ReturnValue.ptr = pMem;
1764 ReturnValue.len = uNewSize;
1765
1766 // Addition won't wrap around over because uNewSize was
1767 // checked to be sure it is less than the pool size.
1768 uFreeOffset = uMemOffset + uNewSize32;
1769 }
1770 }
1771 } else {
1772 // ALLOCATION MODE
1773 // uPoolSize - uFreeOffset will not underflow because this
1774 // pool implementation makes sure uFreeOffset is always
1775 // smaller than uPoolSize through this check here and
1776 // reallocation case.
1777 if(uNewSize <= uPoolSize - uFreeOffset) {
1778 ReturnValue.len = uNewSize;
1779 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001780 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001781 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001782 }
1783 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001784 if(pMem) {
1785 // FREE MODE
1786 // Cast is safe because of limit on pool size in
1787 // QCBORDecode_SetMemPool()
1788 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1789 } else {
1790 // DESTRUCT MODE
1791 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001792 }
1793 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001794
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001795 UsefulBuf Pool = {pPool, uPoolSize};
1796 MemPool_Pack(Pool, uFreeOffset);
1797
1798Done:
1799 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001800}
1801
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001802
Laurence Lundbladef6531662018-12-04 10:42:22 +09001803/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001804 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001805 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001806QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1807 UsefulBuf Pool,
1808 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001809{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001810 // The pool size and free mem offset are packed into the beginning
1811 // of the pool memory. This compile time check make sure the
1812 // constant in the header is correct. This check should optimize
1813 // down to nothing.
1814 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001815 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001816 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001817
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001818 // The pool size and free offset packed in to the beginning of pool
1819 // memory are only 32-bits. This check will optimize out on 32-bit
1820 // machines.
1821 if(Pool.len > UINT32_MAX) {
1822 return QCBOR_ERR_BUFFER_TOO_LARGE;
1823 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001824
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001825 // This checks that the pool buffer given is big enough.
1826 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1827 return QCBOR_ERR_BUFFER_TOO_SMALL;
1828 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001829
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001830 pMe->StringAllocator.pfAllocator = MemPool_Function;
1831 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1832 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001833
Laurence Lundblade30816f22018-11-10 13:40:22 +07001834 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001835}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001836
Laurence Lundblade1341c592020-04-11 14:19:05 -07001837#include <stdio.h>
1838void printdecode(QCBORDecodeContext *pMe, const char *szName)
1839{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001840 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1841 szName,
1842 (uint32_t)pMe->InBuf.cursor,
1843 (uint32_t)pMe->InBuf.UB.len);
1844/* for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
1845 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1846 break;
1847 }
1848 printf(" %2d %5d %s %6u %2d %d\n",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001849 i,
1850 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001851 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1852 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1853 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001854 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001855 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1856 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001857 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001858
Laurence Lundblade1341c592020-04-11 14:19:05 -07001859 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001860 printf("\n"); */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001861}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001862
1863
1864/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001865 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001866 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001867static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001868ConsumeItem(QCBORDecodeContext *pMe,
1869 const QCBORItem *pItemToConsume,
1870 uint_fast8_t *puNextNestLevel)
1871{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001872 QCBORError nReturn;
1873 QCBORItem Item;
1874
1875 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001876
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001877 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001878 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001879
Laurence Lundblade1341c592020-04-11 14:19:05 -07001880 /* This works for definite and indefinite length
1881 * maps and arrays by using the nesting level
1882 */
1883 do {
1884 nReturn = QCBORDecode_GetNext(pMe, &Item);
1885 if(nReturn != QCBOR_SUCCESS) {
1886 goto Done;
1887 }
1888 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001889
Laurence Lundblade1341c592020-04-11 14:19:05 -07001890 if(puNextNestLevel != NULL) {
1891 *puNextNestLevel = Item.uNextNestLevel;
1892 }
1893 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001894
Laurence Lundblade1341c592020-04-11 14:19:05 -07001895 } else {
1896 /* item_to_consume is not a map or array */
1897 if(puNextNestLevel != NULL) {
1898 /* Just pass the nesting level through */
1899 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1900 }
1901 nReturn = QCBOR_SUCCESS;
1902 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001903
1904Done:
1905 return nReturn;
1906}
1907
1908
Laurence Lundblade1341c592020-04-11 14:19:05 -07001909/* Return true if the labels in Item1 and Item2 are the same.
1910 Works only for integer and string labels. Returns false
1911 for any other type. */
1912static inline bool
1913MatchLabel(QCBORItem Item1, QCBORItem Item2)
1914{
1915 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1916 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1917 return true;
1918 }
1919 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
1920 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1921 return true;
1922 }
1923 }
1924 /* Other label types are never matched */
1925 return false;
1926}
1927
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001928/*
1929 * Public function. qcbor_util.h
1930 */
1931QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001932GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001933{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001934 QCBORItem *pIterator;
1935 QCBORError nReturn;
1936
1937
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001938
Laurence Lundblade1341c592020-04-11 14:19:05 -07001939 printdecode(pMe, "GetItemsInMapStart");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001940
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001941
Laurence Lundblade1341c592020-04-11 14:19:05 -07001942 // TODO: check we are in map mode
1943
1944 /* Clear structure holding the items found */
1945 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1946 pIterator->uDataType = QCBOR_TYPE_NONE;
1947 }
1948
1949 // Save the cursor and such used for pre-order traversal
1950/* const size_t uSave = UsefulInputBuf_Tell(&(pMe->InBuf));
1951 const uint16_t uSaveCount = pMe->nesting.pCurrent->uCount;
1952 struct nesting_decode_level *pSaveCurrent = pMe->nesting.pCurrent;
1953*/
1954 QCBORDecodeNesting N = pMe->nesting;
1955
1956 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1957 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
1958 }
1959
1960 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1961
1962 /* Loop over all the items in the map. They could be
1963 * deeply nested and this should handle both definite
1964 * and indefinite length maps and arrays, so this
1965 * adds some complexity. */
1966 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
1967
1968 while(1) {
1969 QCBORItem Item;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001970
Laurence Lundblade1341c592020-04-11 14:19:05 -07001971 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001972
Laurence Lundblade1341c592020-04-11 14:19:05 -07001973 printdecode(pMe, "GetItemsInMapMid1");
1974
1975 if((nReturn = QCBORDecode_GetNext(pMe, &Item)) != QCBOR_SUCCESS) {
1976 /* Got non-well-formed CBOR */
1977 goto Done;
1978 }
1979
1980 printdecode(pMe, "GetItemsInMapMid2");
1981
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001982
Laurence Lundblade1341c592020-04-11 14:19:05 -07001983 // Loop over all the items to check this item against
1984 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1985 if(MatchLabel(Item, *pIterator)) {
1986 // A label match has been found
1987 if(pIterator->uDataType != QCBOR_TYPE_NONE) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001988 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
1989 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001990 }
1991
1992 /* Successful match. Return the item. */
1993 *pIterator = Item;
1994 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001995 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001996 }
1997 }
1998 }
1999
2000 /* Still have to consume the item that did or didn't match.
2001 The item could be a deeply nested array or map. */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002002
2003 /* Only looking at top-level data items, so just consume any
2004 * map or array encountered.*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002005 uint_fast8_t uNextNestLevel;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002006
Laurence Lundblade1341c592020-04-11 14:19:05 -07002007 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2008 if(nReturn) {
2009 goto Done;
2010 }
2011 if(uNextNestLevel < uMapNestLevel) {
2012 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002013 /* Got all the items in the map. This is the non-error exit
2014 * from the loop. */
2015 // Cast OK because encoded CBOR is limited to UINT32_MAX
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002016 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2017 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2018 // TODO: is zero *puOffset OK?
2019 if(puEndOffset) {
2020 *puEndOffset = uEndOffset;
2021 }
2022 // TODO: record the offset here for exit to save CPU time
Laurence Lundblade1341c592020-04-11 14:19:05 -07002023 break;
2024 }
2025 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002026
2027Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002028 printdecode(pMe, "GetItemsInMapBeforeDone");
2029
2030
2031 // Restore cursor for pre-order traversal
2032 /*
2033 pMe->nesting.pCurrent = pSaveCurrent;
2034 pMe->nesting.pCurrent->uCount = uSaveCount;
2035 UsefulInputBuf_Seek(&(pMe->InBuf), uSave);
2036 */
2037 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002038
Laurence Lundblade1341c592020-04-11 14:19:05 -07002039 printdecode(pMe, "GetItemsInMapEnd");
2040
2041 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002042}
2043
2044void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2045{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002046 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002047
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002048/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002049 if(pMe->uMapEndOffset) {
2050 uEndOffset = pMe->uMapEndOffset;
2051 // It is only valid once.
2052 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002053 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002054 QCBORItem Dummy;
2055
2056 Dummy.uLabelType = QCBOR_TYPE_NONE;
2057
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002058 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002059
2060 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002061// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002062
2063 printdecode(pMe, "start exit");
2064 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2065
2066 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2067 pMe->nesting.pCurrent->uCount = 1;
2068 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002069 pMe->nesting.pCurrent->uMapMode = 0;
2070
2071 DecodeNesting_DecrementCount(&(pMe->nesting), true);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002072 printdecode(pMe, "end exit");
2073
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002074}
2075
2076
2077QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002078 int64_t nLabel,
2079 uint8_t uQcborType,
2080 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002081{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002082 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002083
Laurence Lundblade1341c592020-04-11 14:19:05 -07002084 One[0].uLabelType = QCBOR_TYPE_INT64;
2085 One[0].label.int64 = nLabel;
2086 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2087
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002088 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002089 if(nReturn) {
2090 return nReturn;
2091 }
2092
2093 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2094 return QCBOR_ERR_NOT_FOUND;
2095 }
2096
2097 if(One[0].uDataType != uQcborType) {
2098 return QCBOR_ERR_UNEXPECTED_TYPE;
2099 }
2100
2101 *pItem = One[0];
2102
2103 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002104}
2105
2106
2107QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002108 const char *szLabel,
2109 uint8_t uQcborType,
2110 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002111{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002112 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002113
Laurence Lundblade1341c592020-04-11 14:19:05 -07002114 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2115 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2116 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2117
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002118 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002119 if(nReturn) {
2120 return nReturn;
2121 }
2122
2123 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2124 return QCBOR_ERR_NOT_FOUND;
2125 }
2126
2127 if(One[0].uDataType != uQcborType) {
2128 return QCBOR_ERR_UNEXPECTED_TYPE;
2129 }
2130
2131 *pItem = One[0];
2132
2133 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002134}
2135
2136
2137void QCBORDecode_GetBstrInMap(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2138{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002139 // TODO: error handling
2140 QCBORItem Item;
2141 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2142 *pBstr = Item.val.string;
2143}
2144
2145void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2146{
2147 // TODO: error handling
2148 QCBORItem Item;
2149 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2150 *pBstr = Item.val.string;
2151}
2152
2153void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2154{
2155 // TODO: error handling
2156 QCBORItem Item;
2157 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2158 *pBstr = Item.val.string;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002159}
2160
2161
2162QCBORError QCBORDecode_EnterMapInMap(QCBORDecodeContext *pMe, int64_t nLabel)
2163{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002164 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002165
Laurence Lundblade1341c592020-04-11 14:19:05 -07002166 One[0].uLabelType = QCBOR_TYPE_INT64;
2167 One[0].label.int64 = nLabel;
2168 One[1].uLabelType = QCBOR_TYPE_NONE;
2169
2170 size_t uOffset;
2171
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002172 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002173
2174 if(nReturn) {
2175 return nReturn;
2176 }
2177
2178 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2179 return QCBOR_ERR_UNEXPECTED_TYPE;
2180 }
2181
2182 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2183
2184 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2185
2186 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2187 pMe->nesting.pCurrent->uMapMode = 1;
2188
2189 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002190}
2191
2192
2193QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2194{
2195 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002196
Laurence Lundblade1341c592020-04-11 14:19:05 -07002197 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2198 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2199 One[1].uLabelType = QCBOR_TYPE_NONE;
2200
2201 size_t uOffset;
2202
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002203 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002204
2205 if(nReturn) {
2206 return nReturn;
2207 }
2208
2209 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2210 return QCBOR_ERR_UNEXPECTED_TYPE;
2211 }
2212
2213 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2214
2215 QCBORItem MapToEnter;
2216 QCBORDecode_GetNext(pMe, &MapToEnter);
2217
2218
2219 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2220
2221 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2222 pMe->nesting.pCurrent->uMapMode = 1;
2223 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2224
2225 printdecode(pMe, "Entered Map in Map");
2226
2227 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002228}
2229
2230
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002231QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t uLabel)
2232{
2233 (void)pMe; (void)uLabel;
2234 return 0;
2235}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002236
Laurence Lundblade1341c592020-04-11 14:19:05 -07002237
2238QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2239{
2240 QCBORItem One[2];
2241
2242 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2243 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2244 One[1].uLabelType = QCBOR_TYPE_NONE;
2245
2246 size_t uOffset;
2247
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002248 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002249
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002250 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002251 return nReturn;
2252 }
2253
2254 if(One[0].uDataType != QCBOR_TYPE_ARRAY) {
2255 return QCBOR_ERR_UNEXPECTED_TYPE;
2256 }
2257
2258 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2259
2260 QCBORItem ArrayToEnter;
2261 QCBORDecode_GetNext(pMe, &ArrayToEnter);
2262
2263
2264 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2265
2266 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2267 pMe->nesting.pCurrent->uMapMode = 1;
2268 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2269
2270 printdecode(pMe, "Entered Array in Map");
2271
2272 return 0;
2273}
2274
2275
2276
2277
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002278/* Next item must be map or this generates an error */
2279QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2280{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002281 QCBORItem Item;
2282 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283
2284 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002285 nReturn = QCBORDecode_GetNext(pMe, &Item);
2286 if(nReturn != QCBOR_SUCCESS) {
2287 return nReturn;
2288 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002289 if(Item.uDataType != QCBOR_TYPE_MAP) {
2290 return QCBOR_ERR_UNEXPECTED_TYPE;
2291 }
2292
Laurence Lundblade1341c592020-04-11 14:19:05 -07002293
2294 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2295 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2296 pMe->nesting.pCurrent->uMapMode = 1;
2297 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002298
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002299 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002300
Laurence Lundblade1341c592020-04-11 14:19:05 -07002301 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002302}
2303
2304
2305
2306QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2307{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002308 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002309}
2310
2311
2312void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2313{
2314 // TODO: error handling
2315 QCBORItem Item;
2316 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2317 *pInt = Item.val.int64;
2318}
2319
2320
Laurence Lundblade1341c592020-04-11 14:19:05 -07002321void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002322{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002323 // TODO: check for map mode
2324 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2325 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2326}
2327
2328
2329QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2330{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002331 QCBORItem Item;
2332 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002333
2334 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002335 nReturn = QCBORDecode_GetNext(pMe, &Item);
2336 if(nReturn != QCBOR_SUCCESS) {
2337 return nReturn;
2338 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002339 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2340 return QCBOR_ERR_UNEXPECTED_TYPE;
2341 }
2342
2343 printdecode(pMe, "EnterArray");
2344
2345 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2346 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2347 pMe->nesting.pCurrent->uMapMode = 1;
2348 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2349
2350
2351 return QCBOR_SUCCESS;
2352}
2353
2354
2355void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2356{
2357 // TODO: make sure we have entered an array
2358 // TODO: combine with code for map? It is the same so far.
2359 size_t uEndOffset;
2360
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002361 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002362 uEndOffset = pMe->uMapEndOffset;
2363 // It is only valid once.
2364 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002365 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002366 QCBORItem Dummy;
2367
2368 Dummy.uLabelType = QCBOR_TYPE_NONE;
2369
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002370 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002371
2372 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002373 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002374
Laurence Lundblade1341c592020-04-11 14:19:05 -07002375 printdecode(pMe, "start exit");
2376 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2377
2378 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2379 pMe->nesting.pCurrent->uCount = 1;
2380 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002381 pMe->nesting.pCurrent->uMapMode = 0;
2382 DecodeNesting_DecrementCount(&(pMe->nesting), true);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002383 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002384}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002385
Laurence Lundbladee6430642020-03-14 21:15:44 -07002386
2387
Laurence Lundbladec4537442020-04-14 18:53:22 -07002388void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002389{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002390 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002391 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002392 return;
2393 }
2394
Laurence Lundbladec4537442020-04-14 18:53:22 -07002395 QCBORError nError;
2396 QCBORItem Item;
2397
2398 nError = QCBORDecode_GetNext(pMe, &Item);
2399 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002400 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002401 return;
2402 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002403
2404 switch(Item.uDataType) {
2405 case QCBOR_TYPE_TRUE:
2406 *pValue = true;
2407 break;
2408
2409 case QCBOR_TYPE_FALSE:
2410 *pValue = false;
2411 break;
2412
2413 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002414 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002415 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002416 }
2417}
2418
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002419#if 0
2420// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002421/* Types of text strings
2422 * Plain, b64, b64url, URI, regex, MIME Text
2423 * One function for each with options to expect plain?
2424 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002425 *
2426 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002427 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002428void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002429{
2430 QCBORItem Item;
2431 QCBORError nError;
2432
2433 nError = QCBORDecode_GetNext(pMe, &Item);
2434 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002435 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002436 return;
2437 }
2438
Laurence Lundbladec4537442020-04-14 18:53:22 -07002439 if(pLabel != NULL) {
2440 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002441 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002442 return;
2443 } else {
2444 // TODO: what about label allocation?
2445 pLabel->uLabelType = Item.uLabelType;
2446 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2447 }
2448 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002449
2450 switch(Item.uDataType) {
2451 case QCBOR_TYPE_TEXT_STRING:
2452 *pValue = Item.val.string;
2453 break;
2454
2455 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002456 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002457 }
2458}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002459#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002460
2461
Laurence Lundbladec4537442020-04-14 18:53:22 -07002462/*
2463 Options for MIME data, CBOR, positive big num, negative big num ??
2464 */
2465void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2466{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002467 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002468 // Already in error state, do nothing
2469 return;
2470 }
2471
2472 QCBORError nError;
2473 QCBORItem Item;
2474
2475 nError = QCBORDecode_GetNext(pMe, &Item);
2476 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002477 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002478 return;
2479 }
2480
2481 if(Item.uDataType == uType) {
2482 *pValue = Item.val.string;
2483 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002484 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002485 }
2486}
2487
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002488void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002489{
2490 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2491}
2492
2493
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002494void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002495{
2496 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2497}
2498
2499
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002500void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002501{
2502 // TODO: do these have to be tagged?
2503 // Probably should allow tagged or untagged, but not wrong-tagged
2504 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2505}
2506
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002507void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002508{
2509 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2510}
2511
2512
2513
Laurence Lundbladee6430642020-03-14 21:15:44 -07002514
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002515typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002516
2517
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002518// The main exponentiator that works on only positive numbers
2519static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002520{
2521 uint64_t uResult;
2522
2523 uResult = uMantissa;
2524
2525 /* This loop will run a maximum of 19 times because
2526 * UINT64_MAX < 10 ^^ 19. More than that will cause
2527 * exit with the overflow error
2528 */
2529 while(nExponent > 0) {
2530 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002531 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002532 }
2533 uResult = uResult * 10;
2534 nExponent--;
2535 }
2536
2537 while(nExponent < 0 ) {
2538 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002539 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002540 }
2541 uResult = uResult / 10;
2542 nExponent--;
2543 }
2544
2545 *puResult = uResult;
2546
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002547 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002548}
2549
2550
Laurence Lundbladee6430642020-03-14 21:15:44 -07002551/* Convert a decimal fraction to an int64_t without using
2552 floating point or math libraries. Most decimal fractions
2553 will not fit in an int64_t and this will error out with
2554 under or overflow
2555 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002556static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002557{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002558 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002559
2560 nResult = nMantissa;
2561
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002562 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002563 * INT64_MAX < 2^31. More than that will cause
2564 * exist with the overflow error
2565 */
2566 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002567 if(nResult > UINT64_MAX >> 1) {
2568 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002569 }
2570 nResult = nResult << 1;
2571 nExponent--;
2572 }
2573
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002574 while(nExponent < 0 ) {
2575 if(nResult == 0) {
2576 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2577 }
2578 nResult = nResult >> 1;
2579 nExponent--;
2580 }
2581
Laurence Lundbladee6430642020-03-14 21:15:44 -07002582 *pnResult = nResult;
2583
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002584 return QCBOR_SUCCESS;
2585}
2586
2587
2588static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2589{
2590 uint64_t uResult;
2591
2592 // Take the absolute value of the mantissa
2593 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2594
2595 // Do the exponentiation of the positive mantissa
2596 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2597 if(uReturn) {
2598 return uReturn;
2599 }
2600
2601 // Error out if too large on the plus side for an int64_t
2602 if(uResult > INT64_MAX) {
2603 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2604 }
2605
2606 // Error out if too large on the negative side for an int64_t
2607 if(uResult < (uint64_t)INT64_MAX+1) {
2608 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2609 of INT64_MIN. This assumes two's compliment representation where
2610 INT64_MIN is one increment farther from 0 than INT64_MAX.
2611 Trying to write -INT64_MIN doesn't work to get this because the
2612 compiler tries to work with an int64_t which can't represent
2613 -INT64_MIN.
2614 */
2615 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2616 }
2617
2618 // Casts are safe because of checks above
2619 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2620
2621 return QCBOR_SUCCESS;
2622}
2623
2624
2625static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2626{
2627 if(nMantissa < 0) {
2628 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2629 }
2630
2631 // Cast to unsigned is OK because of check for negative
2632 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2633 // Exponentiation is straight forward
2634 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2635}
2636
2637
2638// TODO: use this or get rid of it
2639QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2640{
2641 uint64_t uResult;
2642
2643 QCBORError uR;
2644
2645 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2646 if(uR) {
2647 return uR;
2648 }
2649
2650 if(uResult > INT64_MAX) {
2651 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2652 }
2653
2654 // Cast is OK because of check above
2655 *pnResult = (int64_t)uResult;
2656
2657 return QCBOR_SUCCESS;
2658}
2659
2660
2661
2662
2663#include <math.h>
2664/*
2665static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2666{
2667 // TODO: checkout exceptions; what is HUGE_VAL?
2668 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2669
2670 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002671 return 0;
2672}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002673*/
2674
2675
2676
2677
2678
Laurence Lundbladee6430642020-03-14 21:15:44 -07002679
2680/*
2681 A) bignum is positive
2682 A1) output is signed INT64_MAX
2683 A2) output is unsigned UINT64_MAX
2684 B) bignum is negative
2685 B1) output is signed INT64_MAX
2686 B2) output is unsigned error
2687 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002688static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002689{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002690 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002691
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002692 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002693 const uint8_t *pByte = BigNum.ptr;
2694 size_t uLen = BigNum.len;
2695 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002696 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002697 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002698 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002699 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002700 }
2701
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002702 *pResult = uResult;
2703 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002704}
2705
Laurence Lundbladec4537442020-04-14 18:53:22 -07002706
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002707#if 0
2708static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002709{
2710 double nResult;
2711
2712 nResult = 0;
2713 const uint8_t *pByte = BigNum.ptr;
2714 size_t uLen = BigNum.len;
2715 /* This will overflow and become the float value INFINITY if the number
2716 is too large to fit. No error will be logged.
2717 TODO: should an error be logged? */
2718 while(uLen--) {
2719 nResult = (nResult * 256) + *pByte;
2720 }
2721
2722 *pResult = nResult;
2723 return 0;
2724}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002725#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002726
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002727static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002728{
2729 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2730}
2731
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002732static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002733{
2734 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002735 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002736 if(n) {
2737 return n;
2738 }
2739 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2740 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002741 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002742}
2743
2744
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002745static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002746{
2747 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002748 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002749 if(n) {
2750 return n;
2751 }
2752 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2753 *pResult = -(int64_t)uResult;
2754 return 0;
2755}
2756
Laurence Lundbladec4537442020-04-14 18:53:22 -07002757// No function to convert a negative bignum to unsigned; it is an error
2758
2759
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002760#if 0
2761static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002762{
2763 int64_t nMantissa;
2764
2765 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2766 if(xx) {
2767 return xx;
2768 }
2769
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002770 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002771}
2772
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002773#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002774
2775
Laurence Lundbladee6430642020-03-14 21:15:44 -07002776
Laurence Lundbladec4537442020-04-14 18:53:22 -07002777
2778/*
2779 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2780 a big float, a decimal fraction or a big num. Conversion will be dones as
2781 expected. Some cases will error out with under or over flow.
2782 */
2783void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002784{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002785 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002786 return;
2787 }
2788
Laurence Lundbladee6430642020-03-14 21:15:44 -07002789 QCBORItem Item;
2790 QCBORError nError;
2791
2792 nError = QCBORDecode_GetNext(pMe, &Item);
2793 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002794 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002795 return;
2796 }
2797
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002798 if(pItem) {
2799 *pItem = Item;
2800 }
2801
Laurence Lundbladee6430642020-03-14 21:15:44 -07002802 switch(Item.uDataType) {
2803 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002804 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002805 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002806 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladee6430642020-03-14 21:15:44 -07002807 *pValue = (int64_t)Item.val.dfnum;
2808 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002809 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002810 }
2811 break;
2812
2813 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002814 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002815 *pValue = Item.val.int64;
2816 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002817 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002818 }
2819 break;
2820
2821 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002822 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002823 if(Item.val.uint64 < INT64_MAX) {
2824 *pValue = Item.val.int64;
2825 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002826 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002827 }
2828 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002829 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002830 }
2831 break;
2832
Laurence Lundbladec4537442020-04-14 18:53:22 -07002833 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002834 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002835 }
2836}
2837
2838/* This works for signed, unsigned and float */
2839void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2840{
2841 QCBORItem Item;
2842 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2843}
2844
2845
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002846// TODO make this inline
2847void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2848{
2849 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2850}
2851
2852
Laurence Lundbladec4537442020-04-14 18:53:22 -07002853
2854/*
2855 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2856 a big float, a decimal fraction or a big num. Conversion will be dones as
2857 expected. Some cases will error out with under or over flow.
2858 */
2859void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2860{
2861 QCBORItem Item;
2862
2863 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2864
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002865 if(pMe->uLastError == QCBOR_SUCCESS) {
2866 // The above conversion succeeded
2867 return;
2868 }
2869
2870 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2871 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002872 return;
2873 }
2874
2875 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002876
2877 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002878 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002879 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002880 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002881 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002882 }
2883 break;
2884
2885 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002886 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002887 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002888 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002889 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002890 }
2891 break;
2892
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002893#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2894 case QCBOR_TYPE_DECIMAL_FRACTION:
2895 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2896 pMe->uLastError = ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
2897 Item.val.expAndMantissa.nExponent,
2898 pValue,
2899 &Exponentitate10UU);
2900 } else {
2901 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2902 }
2903 break;
2904
2905 case QCBOR_TYPE_BIGFLOAT:
2906 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
2907 pMe->uLastError = ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
2908 Item.val.expAndMantissa.nExponent,
2909 pValue,
2910 &Exponentitate2UU);
2911 } else {
2912 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2913 }
2914 break;
2915
2916
Laurence Lundbladee6430642020-03-14 21:15:44 -07002917 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002918 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002919 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002920 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2921 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002922 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002923 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002924 pValue,
2925 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002926 }
2927 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002928 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002929 }
2930 break;
2931
2932 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002933 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002934 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002935 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2936 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002937 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002938 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002939 pValue,
2940 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002941 }
2942 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002943 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002944 }
2945 break;
2946
2947 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002948 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002949 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002950 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2951 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002952 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002953 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002954 pValue,
2955 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002956 }
2957 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002958 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002959 }
2960 break;
2961
2962 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002963 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002964 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002965 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2966 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002967 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002968 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002969 pValue,
2970 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002971 }
2972 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002973 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002974 }
2975 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002976
2977 default:
2978 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2979#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002980 }
2981}
2982
Laurence Lundbladec4537442020-04-14 18:53:22 -07002983
2984
2985void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
2986{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002987 if(pMe->uLastError != QCBOR_SUCCESS) {
2988 return;
2989 }
2990
Laurence Lundbladec4537442020-04-14 18:53:22 -07002991 QCBORItem Item;
2992 QCBORError nError;
2993
2994 nError = QCBORDecode_GetNext(pMe, &Item);
2995 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002996 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002997 return;
2998 }
2999
3000 switch(Item.uDataType) {
3001 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003002 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003003 if(Item.val.dfnum >= 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003004 // TODO: over/underflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07003005 *pValue = (uint64_t)Item.val.dfnum;
3006 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003007 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003008 }
3009 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003010 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003011 }
3012 break;
3013
3014 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003015 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003016 if(Item.val.int64 >= 0) {
3017 *pValue = (uint64_t)Item.val.int64;
3018 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003019 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003020 }
3021 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003022 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003023 }
3024 break;
3025
3026 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003027 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003028 *pValue = Item.val.uint64;
3029 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003030 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003031 }
3032 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003033
3034 default:
3035 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003036 }
3037}
3038
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003039
3040/* This works for signed, unsigned and float */
3041void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003042{
3043 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003044 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3045}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003046
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003047
3048// TODO make this inline
3049void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3050{
3051 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3052}
3053
3054
3055
3056
3057void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3058{
3059 QCBORItem Item;
3060
3061 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3062
3063 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003064 return;
3065 }
3066
Laurence Lundbladee6430642020-03-14 21:15:44 -07003067 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003068
3069 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003070 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3071 pMe->uLastError = ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003072 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003073 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003074 }
3075 break;
3076
3077 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003078 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3079 pMe->uLastError = ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003080 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003081 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003082 }
3083 break;
3084
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003085#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3086
3087 case QCBOR_TYPE_DECIMAL_FRACTION:
3088 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3089 pMe->uLastError = ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
3090 Item.val.expAndMantissa.nExponent,
3091 pValue,
3092 Exponentitate10UU);
3093 } else {
3094 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3095 }
3096 break;
3097
3098 case QCBOR_TYPE_BIGFLOAT:
3099 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3100 pMe->uLastError = ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
3101 Item.val.expAndMantissa.nExponent,
3102 pValue,
3103 Exponentitate2UU);
3104 } else {
3105 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3106 }
3107 break;
3108
3109
3110
Laurence Lundbladee6430642020-03-14 21:15:44 -07003111 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003112 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003113 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003114 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3115 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003116 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003117 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003118 pValue,
3119 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003120 }
3121 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003122 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003123 }
3124 break;
3125
3126 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003127 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003128 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003129 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3130 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003131 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003132 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003133 pValue,
3134 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003135 }
3136 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003137 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003138 }
3139 break;
3140
3141 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003142 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003143 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003144 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3145 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003146 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003147 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003148 pValue,
3149 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003150 }
3151 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003152 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003153 }
3154 break;
3155
3156 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003157 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003158 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003159 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3160 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003161 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003162 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003163 pValue,
3164 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003165 }
3166 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003167 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003168 }
3169 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003170#endif
3171 default:
3172 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003173 }
3174}
3175
Laurence Lundbladec4537442020-04-14 18:53:22 -07003176
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003177
3178#if 0
Laurence Lundbladec4537442020-04-14 18:53:22 -07003179/*
3180
3181 Convert from bignums,
3182
3183 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003184void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003185{
3186 /* the same range of conversions */
3187
Laurence Lundbladec4537442020-04-14 18:53:22 -07003188 /* Conversion from bignums, decimal fractions and such will be interesting */
3189
3190 QCBORItem Item;
3191 QCBORError nError;
3192
3193 nError = QCBORDecode_GetNext(pMe, &Item);
3194 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003195 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003196 return;
3197 }
3198
Laurence Lundbladec4537442020-04-14 18:53:22 -07003199
3200 switch(Item.uDataType) {
3201 case QCBOR_TYPE_FLOAT:
3202 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3203 *pValue = Item.val.dfnum;
3204 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003205 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003206 }
3207 break;
3208
3209 case QCBOR_TYPE_INT64:
3210 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3211 // TODO: how does this work?
3212 *pValue = (double)Item.val.int64;
3213 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003214 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003215 }
3216 break;
3217
3218 case QCBOR_TYPE_UINT64:
3219 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3220 *pValue = (double)Item.val.uint64;
3221 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003222 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003223 }
3224 break;
3225
3226 case QCBOR_TYPE_DECIMAL_FRACTION:
3227 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003228 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003229 Item.val.expAndMantissa.nExponent,
3230 pValue);
3231 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003232 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003233 }
3234 break;
3235
3236 case QCBOR_TYPE_BIGFLOAT:
3237 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003238 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003239 Item.val.expAndMantissa.nExponent,
3240 pValue);
3241 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003242 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003243 }
3244 break;
3245
3246 case QCBOR_TYPE_POSBIGNUM:
3247 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003248 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003249 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003250 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003251 }
3252 break;
3253
3254 case QCBOR_TYPE_NEGBIGNUM:
3255 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003256 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003257 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003258 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003259 }
3260 break;
3261
3262 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3263 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3264 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003265 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3266 if(!pMe->uLastError) {
3267 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003268 Item.val.expAndMantissa.nExponent,
3269 pValue);
3270 }
3271 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003272 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003273 }
3274 break;
3275
3276 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3277 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3278 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003279 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3280 if(!pMe->uLastError) {
3281 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003282 Item.val.expAndMantissa.nExponent,
3283 pValue);
3284 }
3285 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003286 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003287 }
3288 break;
3289
3290 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3291 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3292 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003293 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3294 if(!pMe->uLastError) {
3295 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003296 Item.val.expAndMantissa.nExponent,
3297 pValue);
3298 }
3299 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003300 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003301 }
3302 break;
3303
3304 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3305 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3306 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003307 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3308 if(!pMe->uLastError) {
3309 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003310 Item.val.expAndMantissa.nExponent,
3311 pValue);
3312 }
3313 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003314 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 }
3316 break;
3317 }
3318
3319
3320
Laurence Lundbladee6430642020-03-14 21:15:44 -07003321}
3322
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003323#endif