blob: 6a174782bb33ea87d6ac58e58643769668cbb48a [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
53inline static int
54IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070055{
56 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
57}
58
Laurence Lundbladeee851742020-01-08 08:37:05 -080059inline static int
60DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070061{
62 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
63}
64
Laurence Lundblade3f9ef042020-04-14 13:15:51 -070065inline static bool
66DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
67{
68 if(!DecodeNesting_IsNested(pNesting)){
69 // Always at end if at the top level of nesting
70 return true;
71 }
72
73 if(!pNesting->pCurrent->uMapMode) {
74 // If not in map mode then it is as IsNested says
75 return false;
76 }
77
78 // In map mode at the current nesting level. In this
79 // mode we are at the end of a pre-order traversal
80 // if the count is zero
81 // TODO: what about indefinite length maps & arrays?
82 return pNesting->pCurrent->uCount == 0;
83}
84
85
Laurence Lundbladeee851742020-01-08 08:37:05 -080086inline static int
87DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070088{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070089 return pNesting->pCurrent->uCount == UINT16_MAX;
90}
91
Laurence Lundbladeee851742020-01-08 08:37:05 -080092inline static uint8_t
93DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +080094{
Laurence Lundbladec5fef682020-01-25 11:38:45 -080095 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -070096 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -080097 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +080098}
99
Laurence Lundbladeee851742020-01-08 08:37:05 -0800100inline static int
101DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700105 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800106
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700107 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
108}
109
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800110// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800111inline static QCBORError
112DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700113{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800114 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800119 // breaks can only occur when the map/array is indefinite length
120 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
121 return QCBOR_ERR_BAD_BREAK;
122 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800123
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 // if all OK, the break reduces the level of nesting
125 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800126
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800127 return QCBOR_SUCCESS;
128}
129
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700130// Called on every single item except breaks including decode of a map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800131inline static void
132DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700134 while(!DecodeNesting_AtEnd(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700135 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800137 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700138 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800139 pNesting->pCurrent->uCount--;
140 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700141
142 if(pNesting->pCurrent->uCount != 0) {
143 // Did not close out an array or map, so nothing further
144 break;
145 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700146
147 if(pNesting->pCurrent->uMapMode) {
148 // In map mode the level-up must be done explicitly
149 break;
150 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700151
152 // Closed out an array or map so level up
153 pNesting->pCurrent--;
154
155 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156 }
157}
158
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800159// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800160inline static QCBORError
161DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700162{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700163 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800164
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800165 if(pItem->val.uCount == 0) {
166 // Nothing to do for empty definite lenth arrays. They are just are
167 // effectively the same as an item that is not a map or array
168 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530169 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800170 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800171
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172 // Error out if arrays is too long to handle
173 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
175 goto Done;
176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800177
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700179 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
180 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
181 goto Done;
182 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800183
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800184 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700185 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800186
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800187 // Record a few details for this nesting level
188 pNesting->pCurrent->uMajorType = pItem->uDataType;
189 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800190
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191Done:
192 return nReturn;;
193}
194
Laurence Lundbladeee851742020-01-08 08:37:05 -0800195inline static void
196DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197{
198 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
199}
200
201
202
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700203/*
204 This list of built-in tags. Only add tags here that are
205 clearly established and useful. Once a tag is added here
206 it can't be taken out as that would break backwards compatibility.
207 There are only 48 slots available forever.
208 */
209static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800210 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
211 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
212 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
213 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
214 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
215 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700216 CBOR_TAG_COSE_ENCRYPTO,
217 CBOR_TAG_COSE_MAC0,
218 CBOR_TAG_COSE_SIGN1,
219 CBOR_TAG_ENC_AS_B64URL,
220 CBOR_TAG_ENC_AS_B64,
221 CBOR_TAG_ENC_AS_B16,
222 CBOR_TAG_CBOR,
223 CBOR_TAG_URI,
224 CBOR_TAG_B64URL,
225 CBOR_TAG_B64,
226 CBOR_TAG_REGEX,
227 CBOR_TAG_MIME,
228 CBOR_TAG_BIN_UUID,
229 CBOR_TAG_CWT,
230 CBOR_TAG_ENCRYPT,
231 CBOR_TAG_MAC,
232 CBOR_TAG_SIGN,
233 CBOR_TAG_GEO_COORD,
234 CBOR_TAG_CBOR_MAGIC
235};
236
237// This is used in a bit of cleverness in GetNext_TaggedItem() to
238// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800239// these types. This will break if the first six items in
240// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
241// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
242#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
243#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
244#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
245#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
246#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
247#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700248
Laurence Lundblade59289e52019-12-30 13:44:37 -0800249#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
250 QCBOR_TAGFLAG_DATE_EPOCH |\
251 QCBOR_TAGFLAG_POS_BIGNUM |\
252 QCBOR_TAGFLAG_NEG_BIGNUM |\
253 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
254 QCBOR_TAGFLAG_BIGFLOAT)
255
256#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
257 QCBOR_TAGFLAG_DATE_EPOCH |\
258 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700259 QCBOR_TAGFLAG_NEG_BIGNUM)
260
261#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
262#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
263#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
264
265static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
266{
267 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800268 /*
269 This is a cross-check to make sure the above array doesn't
270 accidentally get made too big. In normal conditions the above
271 test should optimize out as all the values are known at compile
272 time.
273 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700274 return -1;
275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800276
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700277 if(uTag > UINT16_MAX) {
278 // This tag map works only on 16-bit tags
279 return -1;
280 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800281
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700282 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
283 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
284 return nTagBitIndex;
285 }
286 }
287 return -1; // Indicates no match
288}
289
290static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
291{
292 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
293 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
294 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
295 }
296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700298 return -1; // Indicates no match
299}
300
301/*
302 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800303
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700304 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800307static QCBORError
308TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
309 uint64_t uTag,
310 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700311{
312 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
313 if(nTagBitIndex >= 0) {
314 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
315 *puTagBitIndex = (uint8_t)nTagBitIndex;
316 return QCBOR_SUCCESS;
317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800318
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319 if(pCallerConfiguredTagMap) {
320 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
321 return QCBOR_ERR_TOO_MANY_TAGS;
322 }
323 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
324 if(nTagBitIndex >= 0) {
325 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
326
327 *puTagBitIndex = (uint8_t)nTagBitIndex;
328 return QCBOR_SUCCESS;
329 }
330 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800331
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700332 return QCBOR_ERR_BAD_OPT_TAG;
333}
334
335
336
Laurence Lundbladeee851742020-01-08 08:37:05 -0800337/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800338 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
339
340 The following four functions are pretty wrappers for invocation of
341 the string allocator supplied by the caller.
342
Laurence Lundbladeee851742020-01-08 08:37:05 -0800343 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800344
Laurence Lundbladeee851742020-01-08 08:37:05 -0800345static inline void
346StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800347{
348 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
349}
350
Laurence Lundbladeee851742020-01-08 08:37:05 -0800351// StringAllocator_Reallocate called with pMem NULL is
352// equal to StringAllocator_Allocate()
353static inline UsefulBuf
354StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
355 void *pMem,
356 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800357{
358 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
359}
360
Laurence Lundbladeee851742020-01-08 08:37:05 -0800361static inline UsefulBuf
362StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800363{
364 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
365}
366
Laurence Lundbladeee851742020-01-08 08:37:05 -0800367static inline void
368StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800369{
370 if(pMe->pfAllocator) {
371 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
372 }
373}
374
375
376
Laurence Lundbladeee851742020-01-08 08:37:05 -0800377/*===========================================================================
378 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700379
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800380 See qcbor/qcbor_decode.h for definition of the object
381 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800382 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700383/*
384 Public function, see header file
385 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800386void QCBORDecode_Init(QCBORDecodeContext *me,
387 UsefulBufC EncodedCBOR,
388 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700389{
390 memset(me, 0, sizeof(QCBORDecodeContext));
391 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800392 // Don't bother with error check on decode mode. If a bad value is
393 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700394 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395 DecodeNesting_Init(&(me->nesting));
396}
397
398
399/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700400 Public function, see header file
401 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800402void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
403 QCBORStringAllocate pfAllocateFunction,
404 void *pAllocateContext,
405 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700406{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800407 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
408 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
409 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700410}
411
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800412
413/*
414 Public function, see header file
415 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800416void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
417 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700418{
419 me->pCallerConfiguredTagList = pTagList;
420}
421
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700422
423/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800424 This decodes the fundamental part of a CBOR data item, the type and
425 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800426
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700427 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800428
Laurence Lundbladeee851742020-01-08 08:37:05 -0800429 This does the network->host byte order conversion. The conversion
430 here also results in the conversion for floats in addition to that
431 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800432
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700433 This returns:
434 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800435
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800436 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800437 tags and floats and length for strings and arrays
438
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800439 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800441
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800442 The int type is preferred to uint8_t for some variables as this
443 avoids integer promotions, can reduce code size and makes
444 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700445 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800446inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
447 int *pnMajorType,
448 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800449 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700450{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700451 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800452
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700453 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800454 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800455
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700456 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800457 const int nTmpMajorType = nInitialByte >> 5;
458 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800460 // Where the number or argument accumulates
461 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800462
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800463 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464 // Need to get 1,2,4 or 8 additional argument bytes Map
465 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800466 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800467
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800468 // Loop getting all the bytes in the argument
469 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800470 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800471 // This shift and add gives the endian conversion
472 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
473 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800475 // The reserved and thus-far unused additional info values
476 nReturn = QCBOR_ERR_UNSUPPORTED;
477 goto Done;
478 } else {
479 // Less than 24, additional info is argument or 31, an indefinite length
480 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700484 if(UsefulInputBuf_GetError(pUInBuf)) {
485 nReturn = QCBOR_ERR_HIT_END;
486 goto Done;
487 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800488
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700489 // All successful if we got here.
490 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800491 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800492 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495Done:
496 return nReturn;
497}
498
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800499
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700500/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800501 CBOR doesn't explicitly specify two's compliment for integers but all
502 CPUs use it these days and the test vectors in the RFC are so. All
503 integers in the CBOR structure are positive and the major type
504 indicates positive or negative. CBOR can express positive integers
505 up to 2^x - 1 where x is the number of bits and negative integers
506 down to 2^x. Note that negative numbers can be one more away from
507 zero than positive. Stdint, as far as I can tell, uses two's
508 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800509
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700510 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800511 used carefully here, and in particular why it isn't used in the interface.
512 Also see
513 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
514
515 Int is used for values that need less than 16-bits and would be subject
516 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518inline static QCBORError
519DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700521 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800522
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700523 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
524 if (uNumber <= INT64_MAX) {
525 pDecodedItem->val.int64 = (int64_t)uNumber;
526 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800527
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528 } else {
529 pDecodedItem->val.uint64 = uNumber;
530 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 }
533 } else {
534 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800535 // CBOR's representation of negative numbers lines up with the
536 // two-compliment representation. A negative integer has one
537 // more in range than a positive integer. INT64_MIN is
538 // equal to (-INT64_MAX) - 1.
539 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800541
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 } else {
543 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000544 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545 nReturn = QCBOR_ERR_INT_OVERFLOW;
546 }
547 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549 return nReturn;
550}
551
552// Make sure #define value line up as DecodeSimple counts on this.
553#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
554#error QCBOR_TYPE_FALSE macro value wrong
555#endif
556
557#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
558#error QCBOR_TYPE_TRUE macro value wrong
559#endif
560
561#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
562#error QCBOR_TYPE_NULL macro value wrong
563#endif
564
565#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
566#error QCBOR_TYPE_UNDEF macro value wrong
567#endif
568
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700569#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
570#error QCBOR_TYPE_BREAK macro value wrong
571#endif
572
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700573#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
574#error QCBOR_TYPE_DOUBLE macro value wrong
575#endif
576
577#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
578#error QCBOR_TYPE_FLOAT macro value wrong
579#endif
580
581/*
582 Decode true, false, floats, break...
583 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800584inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700587 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundbladeee851742020-01-08 08:37:05 -0800589 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800590 // above make sure uAdditionalInfo values line up with uDataType values.
591 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
592 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800593
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800594 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
596 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800597
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700598 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700599 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
600 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700601 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700602 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700603 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
604 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700605 break;
606 case DOUBLE_PREC_FLOAT:
607 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700608 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700609 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611 case CBOR_SIMPLEV_FALSE: // 20
612 case CBOR_SIMPLEV_TRUE: // 21
613 case CBOR_SIMPLEV_NULL: // 22
614 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700615 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618 case CBOR_SIMPLEV_ONEBYTE: // 24
619 if(uNumber <= CBOR_SIMPLE_BREAK) {
620 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700621 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622 goto Done;
623 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800624 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 default: // 0-19
628 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 /*
630 DecodeTypeAndNumber will make uNumber equal to
631 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
632 safe because the 2, 4 and 8 byte lengths of uNumber are in
633 the double/float cases above
634 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 pDecodedItem->val.uSimple = (uint8_t)uNumber;
636 break;
637 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639Done:
640 return nReturn;
641}
642
643
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530645 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800647inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
648 int nMajorType,
649 uint64_t uStrLen,
650 UsefulInputBuf *pUInBuf,
651 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700652{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700653 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800654
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800655 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
656 // This check makes the casts to size_t below safe.
657
658 // 4 bytes less than the largest sizeof() so this can be tested by
659 // putting a SIZE_MAX length in the CBOR test input (no one will
660 // care the limit on strings is 4 bytes shorter).
661 if(uStrLen > SIZE_MAX-4) {
662 nReturn = QCBOR_ERR_STRING_TOO_LONG;
663 goto Done;
664 }
665
666 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530667 if(UsefulBuf_IsNULLC(Bytes)) {
668 // Failed to get the bytes for this string item
669 nReturn = QCBOR_ERR_HIT_END;
670 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700671 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530672
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800673 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530674 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530676 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700677 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530678 goto Done;
679 }
680 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800681 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530682 } else {
683 // Normal case with no string allocator
684 pDecodedItem->val.string = Bytes;
685 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 // Cast because ternary operator causes promotion to integer
688 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
689 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530691Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700692 return nReturn;
693}
694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697
698
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699
700
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701// Make sure the constants align as this is assumed by
702// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700703#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
704#error QCBOR_TYPE_ARRAY value not lined up with major type
705#endif
706#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
707#error QCBOR_TYPE_MAP value not lined up with major type
708#endif
709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800711 This gets a single data item and decodes it including preceding
712 optional tagging. This does not deal with arrays and maps and nesting
713 except to decode the data item introducing them. Arrays and maps are
714 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800715
Laurence Lundbladeee851742020-01-08 08:37:05 -0800716 Errors detected here include: an array that is too long to decode,
717 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800719static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
720 QCBORItem *pDecodedItem,
721 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700722{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700723 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800724
Laurence Lundbladeee851742020-01-08 08:37:05 -0800725 /*
726 Get the major type and the number. Number could be length of more
727 bytes or the value depending on the major type nAdditionalInfo is
728 an encoding of the length of the uNumber and is needed to decode
729 floats and doubles
730 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800731 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800734
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700735 memset(pDecodedItem, 0, sizeof(QCBORItem));
736
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800737 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundbladeee851742020-01-08 08:37:05 -0800739 // Error out here if we got into trouble on the type and number. The
740 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700741 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700742 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700743 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladeee851742020-01-08 08:37:05 -0800745 // At this point the major type and the value are valid. We've got
746 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700748 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
749 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700751 nReturn = QCBOR_ERR_BAD_INT;
752 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700754 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800756
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700757 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
758 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
760 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
761 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
762 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530763 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800765 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766 }
767 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
770 case CBOR_MAJOR_TYPE_MAP: // Major type 5
771 // Record the number of items in the array or map
772 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
773 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
774 goto Done;
775 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530777 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700778 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800779 // type conversion OK because of check above
780 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800782 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800783 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
784 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800786
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700787 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800788 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700789 nReturn = QCBOR_ERR_BAD_INT;
790 } else {
791 pDecodedItem->val.uTagV = uNumber;
792 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
793 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundbladeee851742020-01-08 08:37:05 -0800796 case CBOR_MAJOR_TYPE_SIMPLE:
797 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800798 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801 default:
802 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700803 nReturn = QCBOR_ERR_UNSUPPORTED;
804 break;
805 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700807Done:
808 return nReturn;
809}
810
811
812
813/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800814 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800815 individual chunk items together into one QCBORItem using the string
816 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530818 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800820static inline QCBORError
821GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700822{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700823 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700824
825 // Get pointer to string allocator. First use is to pass it to
826 // GetNext_Item() when option is set to allocate for *every* string.
827 // Second use here is to allocate space to coallese indefinite
828 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800829 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
830 &(me->StringAllocator) :
831 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800832
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700833 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800834 nReturn = GetNext_Item(&(me->InBuf),
835 pDecodedItem,
836 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700837 if(nReturn) {
838 goto Done;
839 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700841 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530842 // code in this function from here down can be eliminated. Run tests, except
843 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800844
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800845 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700846 const uint8_t uStringType = pDecodedItem->uDataType;
847 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 goto Done; // no need to do any work here on non-string types
849 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800850
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800851 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530852 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800853 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530856 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800857 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700858 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
859 goto Done;
860 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700862 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700863 UsefulBufC FullString = NULLUsefulBufC;
864
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700866 // Get item for next chunk
867 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700868 // NULL string allocator passed here. Do not need to allocate
869 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800870 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700872 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800874
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530875 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700876 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800877 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530879 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 break;
881 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800882
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700883 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530884 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700885 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 if(StringChunkItem.uDataType != uStringType ||
887 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700888 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889 break;
890 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800893 // The first time throurgh FullString.ptr is NULL and this is
894 // equivalent to StringAllocator_Allocate()
895 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
896 UNCONST_POINTER(FullString.ptr),
897 FullString.len + StringChunkItem.val.string.len);
898
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530900 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700901 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 break;
903 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800904
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700905 // Copy new string chunk at the end of string so far.
906 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700907 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800909 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
910 // Getting the item failed, clean up the allocated memory
911 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700912 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700914Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 return nReturn;
916}
917
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918
919/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800920 Gets all optional tag data items preceding a data item that is not an
921 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923static QCBORError
924GetNext_TaggedItem(QCBORDecodeContext *me,
925 QCBORItem *pDecodedItem,
926 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700928 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700929 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700930 uint64_t uTagBits = 0;
931 if(pTags) {
932 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700933 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700934
Laurence Lundblade59289e52019-12-30 13:44:37 -0800935 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700936 for(;;) {
937 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700938 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700939 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700940 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700942 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
943 // Successful exit from loop; maybe got some tags, maybe not
944 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945 break;
946 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700948 uint8_t uTagBitIndex;
949 // Tag was mapped, tag was not mapped, error with tag list
950 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800951
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700952 case QCBOR_SUCCESS:
953 // Successfully mapped the tag
954 uTagBits |= 0x01ULL << uTagBitIndex;
955 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700957 case QCBOR_ERR_BAD_OPT_TAG:
958 // Tag is not recognized. Do nothing
959 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700961 default:
962 // Error Condition
963 goto Done;
964 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800965
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700966 if(pTags) {
967 // Caller wants all tags recorded in the provided buffer
968 if(pTags->uNumUsed >= pTags->uNumAllocated) {
969 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
970 goto Done;
971 }
972 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
973 pTags->uNumUsed++;
974 }
975 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700977Done:
978 return nReturn;
979}
980
981
982/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800983 This layer takes care of map entries. It combines the label and data
984 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700985 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800986static inline QCBORError
987GetNext_MapEntry(QCBORDecodeContext *me,
988 QCBORItem *pDecodedItem,
989 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700990{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700991 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700992 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700993 if(nReturn)
994 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800995
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800996 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700997 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800998 goto Done;
999 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001001 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1002 // In a map and caller wants maps decoded, not treated as arrays
1003
1004 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1005 // If in a map and the right decoding mode, get the label
1006
Laurence Lundbladeee851742020-01-08 08:37:05 -08001007 // Save label in pDecodedItem and get the next which will
1008 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001009 QCBORItem LabelItem = *pDecodedItem;
1010 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1011 if(nReturn)
1012 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301014 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001015
1016 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1017 // strings are always good labels
1018 pDecodedItem->label.string = LabelItem.val.string;
1019 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1020 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001021 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001022 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1023 goto Done;
1024 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1025 pDecodedItem->label.int64 = LabelItem.val.int64;
1026 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1027 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1028 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1029 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1030 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1031 pDecodedItem->label.string = LabelItem.val.string;
1032 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1033 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1034 } else {
1035 // label is not an int or a string. It is an arrray
1036 // or a float or such and this implementation doesn't handle that.
1037 // Also, tags on labels are ignored.
1038 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1039 goto Done;
1040 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001041 }
1042 } else {
1043 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001044 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1045 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1046 goto Done;
1047 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001048 // Decoding a map as an array
1049 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001050 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1051 // Cast is needed because of integer promotion
1052 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001053 }
1054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001056Done:
1057 return nReturn;
1058}
1059
1060
1061/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001062 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001063 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001065QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1066 QCBORItem *pDecodedItem,
1067 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001069 // Stack ptr/int: 2, QCBORItem : 64
1070
Laurence Lundblade30816f22018-11-10 13:40:22 +07001071 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade1341c592020-04-11 14:19:05 -07001073 // Check if there are an TODO: incomplete comment
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001074 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1075 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1076 goto Done;
1077 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001078
1079 // This is to handle map and array mode
1080 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1081 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1082 goto Done;
1083 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001084
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001085 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001086 if(nReturn) {
1087 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001088 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301089
1090 // Break ending arrays/maps are always processed at the end of this function.
1091 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301092 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301093 nReturn = QCBOR_ERR_BAD_BREAK;
1094 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301095 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001096
Laurence Lundblade6de37062018-10-15 12:22:42 +05301097 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301098 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301099 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001100
Laurence Lundblade6de37062018-10-15 12:22:42 +05301101 // Process the item just received for descent or decrement, and
1102 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001103 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001104 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001105 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001106 // Maps and arrays do count in as items in the map/array that encloses
1107 // them so a decrement needs to be done for them too, but that is done
1108 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001109 // are opened with the exception of an empty map or array.
1110 if(pDecodedItem->val.uCount == 0) {
1111 DecodeNesting_DecrementCount(&(me->nesting));
1112 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001113 } else {
1114 // Decrement the count of items in the enclosing map/array
1115 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301116 // triggers a decrement in the map/array above that and
1117 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001118 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001119 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301120 if(nReturn) {
1121 goto Done;
1122 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001123
Laurence Lundblade6de37062018-10-15 12:22:42 +05301124 // For indefinite length maps/arrays, looking at any and
1125 // all breaks that might terminate them. The equivalent
1126 // for definite length maps/arrays happens in
1127 // DecodeNesting_DecrementCount().
1128 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1129 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1130 // Peek forward one item to see if it is a break.
1131 QCBORItem Peek;
1132 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1133 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1134 if(nReturn) {
1135 goto Done;
1136 }
1137 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1138 // It is not a break, rewind so it can be processed normally.
1139 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1140 break;
1141 }
1142 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301143 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301144 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1145 if(nReturn) {
1146 // break occured outside of an indefinite length array/map
1147 goto Done;
1148 }
1149 }
1150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundblade6de37062018-10-15 12:22:42 +05301152 // Tell the caller what level is next. This tells them what maps/arrays
1153 // were closed out and makes it possible for them to reconstruct
1154 // the tree with just the information returned by GetNext
1155 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001156
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001157Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001158 if(nReturn != QCBOR_SUCCESS) {
1159 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1160 memset(pDecodedItem, 0, sizeof(QCBORItem));
1161 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001162 return nReturn;
1163}
1164
1165
Laurence Lundblade59289e52019-12-30 13:44:37 -08001166/*
1167 Mostly just assign the right data type for the date string.
1168 */
1169inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1170{
1171 // Stack Use: UsefulBuf 1 16
1172 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1173 return QCBOR_ERR_BAD_OPT_TAG;
1174 }
1175
1176 const UsefulBufC Temp = pDecodedItem->val.string;
1177 pDecodedItem->val.dateString = Temp;
1178 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1179 return QCBOR_SUCCESS;
1180}
1181
1182
1183/*
1184 Mostly just assign the right data type for the bignum.
1185 */
1186inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1187{
1188 // Stack Use: UsefulBuf 1 -- 16
1189 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1190 return QCBOR_ERR_BAD_OPT_TAG;
1191 }
1192 const UsefulBufC Temp = pDecodedItem->val.string;
1193 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001194 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001195 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1196 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001197 return QCBOR_SUCCESS;
1198}
1199
1200
1201/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001202 The epoch formatted date. Turns lots of different forms of encoding
1203 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001204 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001205static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001206{
1207 // Stack usage: 1
1208 QCBORError nReturn = QCBOR_SUCCESS;
1209
1210 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1211
1212 switch (pDecodedItem->uDataType) {
1213
1214 case QCBOR_TYPE_INT64:
1215 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1216 break;
1217
1218 case QCBOR_TYPE_UINT64:
1219 if(pDecodedItem->val.uint64 > INT64_MAX) {
1220 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1221 goto Done;
1222 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001223 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001224 break;
1225
1226 case QCBOR_TYPE_DOUBLE:
1227 {
1228 // This comparison needs to be done as a float before
1229 // conversion to an int64_t to be able to detect doubles
1230 // that are too large to fit into an int64_t. A double
1231 // has 52 bits of preceision. An int64_t has 63. Casting
1232 // INT64_MAX to a double actually causes a round up which
1233 // is bad and wrong for the comparison because it will
1234 // allow conversion of doubles that can't fit into a
1235 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1236 // the cutoff point as if that rounds up in conversion to
1237 // double it will still be less than INT64_MAX. 0x7ff is
1238 // picked because it has 11 bits set.
1239 //
1240 // INT64_MAX seconds is on the order of 10 billion years,
1241 // and the earth is less than 5 billion years old, so for
1242 // most uses this conversion error won't occur even though
1243 // doubles can go much larger.
1244 //
1245 // Without the 0x7ff there is a ~30 minute range of time
1246 // values 10 billion years in the past and in the future
1247 // where this this code would go wrong.
1248 const double d = pDecodedItem->val.dfnum;
1249 if(d > (double)(INT64_MAX - 0x7ff)) {
1250 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1251 goto Done;
1252 }
1253 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1254 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1255 }
1256 break;
1257
1258 default:
1259 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1260 goto Done;
1261 }
1262 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1263
1264Done:
1265 return nReturn;
1266}
1267
1268
1269#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1270/*
1271 Decode decimal fractions and big floats.
1272
1273 When called pDecodedItem must be the array that is tagged as a big
1274 float or decimal fraction, the array that has the two members, the
1275 exponent and mantissa.
1276
1277 This will fetch and decode the exponent and mantissa and put the
1278 result back into pDecodedItem.
1279 */
1280inline static QCBORError
1281QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1282{
1283 QCBORError nReturn;
1284
1285 // --- Make sure it is an array; track nesting level of members ---
1286 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1287 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1288 goto Done;
1289 }
1290
1291 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001292 // definite length arrays, but not for indefnite. Instead remember
1293 // the nesting level the two integers must be at, which is one
1294 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001295 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1296
1297 // --- Is it a decimal fraction or a bigfloat? ---
1298 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1299 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1300
1301 // --- Get the exponent ---
1302 QCBORItem exponentItem;
1303 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1304 if(nReturn != QCBOR_SUCCESS) {
1305 goto Done;
1306 }
1307 if(exponentItem.uNestingLevel != nNestLevel) {
1308 // Array is empty or a map/array encountered when expecting an int
1309 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1310 goto Done;
1311 }
1312 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1313 // Data arriving as an unsigned int < INT64_MAX has been converted
1314 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1315 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1316 // will be too large for this to handle and thus an error that will
1317 // get handled in the next else.
1318 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1319 } else {
1320 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1321 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1322 goto Done;
1323 }
1324
1325 // --- Get the mantissa ---
1326 QCBORItem mantissaItem;
1327 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1328 if(nReturn != QCBOR_SUCCESS) {
1329 goto Done;
1330 }
1331 if(mantissaItem.uNestingLevel != nNestLevel) {
1332 // Mantissa missing or map/array encountered when expecting number
1333 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1334 goto Done;
1335 }
1336 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1337 // Data arriving as an unsigned int < INT64_MAX has been converted
1338 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1339 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1340 // will be too large for this to handle and thus an error that
1341 // will get handled in an else below.
1342 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1343 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1344 // Got a good big num mantissa
1345 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1346 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001347 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1348 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1349 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001350 } else {
1351 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1352 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1353 goto Done;
1354 }
1355
1356 // --- Check that array only has the two numbers ---
1357 if(mantissaItem.uNextNestLevel == nNestLevel) {
1358 // Extra items in the decimal fraction / big num
1359 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1360 goto Done;
1361 }
1362
1363Done:
1364
1365 return nReturn;
1366}
1367#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1368
1369
1370/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001371 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001372 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001373QCBORError
1374QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1375 QCBORItem *pDecodedItem,
1376 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001377{
1378 QCBORError nReturn;
1379
1380 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1381 if(nReturn != QCBOR_SUCCESS) {
1382 goto Done;
1383 }
1384
1385#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1386#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1387#else
1388#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1389#endif
1390
1391 // Only pay attention to tags this code knows how to decode.
1392 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1393 case 0:
1394 // No tags at all or none we know about. Nothing to do.
1395 // This is the pass-through path of this function
1396 // that will mostly be taken when decoding any item.
1397 break;
1398
1399 case QCBOR_TAGFLAG_DATE_STRING:
1400 nReturn = DecodeDateString(pDecodedItem);
1401 break;
1402
1403 case QCBOR_TAGFLAG_DATE_EPOCH:
1404 nReturn = DecodeDateEpoch(pDecodedItem);
1405 break;
1406
1407 case QCBOR_TAGFLAG_POS_BIGNUM:
1408 case QCBOR_TAGFLAG_NEG_BIGNUM:
1409 nReturn = DecodeBigNum(pDecodedItem);
1410 break;
1411
1412#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1413 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1414 case QCBOR_TAGFLAG_BIGFLOAT:
1415 // For aggregate tagged types, what goes into pTags is only collected
1416 // from the surrounding data item, not the contents, so pTags is not
1417 // passed on here.
1418
1419 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1420 break;
1421#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1422
1423 default:
1424 // Encountering some mixed-up CBOR like something that
1425 // is tagged as both a string and integer date.
1426 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1427 }
1428
1429Done:
1430 if(nReturn != QCBOR_SUCCESS) {
1431 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1432 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1433 }
1434 return nReturn;
1435}
1436
1437
1438/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001439 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001440 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001441QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001442{
1443 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1444}
1445
1446
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001447/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301448 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301449 next one down. If a layer has no work to do for a particular item
1450 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001451
Laurence Lundblade59289e52019-12-30 13:44:37 -08001452 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1453 tagged data items, turning them into the local C representation.
1454 For the most simple it is just associating a QCBOR_TYPE with the data. For
1455 the complex ones that an aggregate of data items, there is some further
1456 decoding and a little bit of recursion.
1457
1458 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301459 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301460 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001461 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301463 - GetNext_MapEntry -- This handles the combining of two
1464 items, the label and the data, that make up a map entry.
1465 It only does work on maps. It combines the label and data
1466 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001467
Laurence Lundblade59289e52019-12-30 13:44:37 -08001468 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1469 tags into bit flags associated with the data item. No actual decoding
1470 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001471
Laurence Lundblade59289e52019-12-30 13:44:37 -08001472 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301473 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301474 string allocater to create contiguous space for the item. It
1475 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001476
Laurence Lundblade59289e52019-12-30 13:44:37 -08001477 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1478 atomic data item has a "major type", an integer "argument" and optionally
1479 some content. For text and byte strings, the content is the bytes
1480 that make up the string. These are the smallest data items that are
1481 considered to be well-formed. The content may also be other data items in
1482 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001483
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001484 Roughly this takes 300 bytes of stack for vars. Need to
1485 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001486
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301487 */
1488
1489
1490/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001491 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001492 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001493int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1494 const QCBORItem *pItem,
1495 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001496{
1497 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001498
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001499 uint8_t uTagBitIndex;
1500 // Do not care about errors in pCallerConfiguredTagMap here. They are
1501 // caught during GetNext() before this is called.
1502 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1503 return 0;
1504 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001505
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001506 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1507 return (uTagBit & pItem->uTagBits) != 0;
1508}
1509
1510
1511/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001512 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001513 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001514QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001515{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001516 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001517
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001518 // Error out if all the maps/arrays are not closed out
1519 if(DecodeNesting_IsNested(&(me->nesting))) {
1520 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1521 goto Done;
1522 }
1523
1524 // Error out if not all the bytes are consumed
1525 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1526 nReturn = QCBOR_ERR_EXTRA_BYTES;
1527 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001528
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001529Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301530 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001531 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001532 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001533
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001534 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001535}
1536
1537
1538
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001539/*
1540
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001541Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundbladeee851742020-01-08 08:37:05 -08001543 - Hit end of input before it was expected while decoding type and
1544 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001546 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001547
Laurence Lundbladeee851742020-01-08 08:37:05 -08001548 - Hit end of input while decoding a text or byte string
1549 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001550
Laurence Lundbladeee851742020-01-08 08:37:05 -08001551 - Encountered conflicting tags -- e.g., an item is tagged both a date
1552 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001553
Laurence Lundbladeee851742020-01-08 08:37:05 -08001554 - Encontered an array or mapp that has too many items
1555 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001556
Laurence Lundbladeee851742020-01-08 08:37:05 -08001557 - Encountered array/map nesting that is too deep
1558 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001559
Laurence Lundbladeee851742020-01-08 08:37:05 -08001560 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1561 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001562
Laurence Lundbladeee851742020-01-08 08:37:05 -08001563 - The type of a map label is not a string or int
1564 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001565
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001566 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001567
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001568 */
1569
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001570
1571
Laurence Lundbladef6531662018-12-04 10:42:22 +09001572
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001573/* ===========================================================================
1574 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001575
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001576 This implements a simple sting allocator for indefinite length
1577 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1578 implements the function type QCBORStringAllocate and allows easy
1579 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001580
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001581 This particular allocator is built-in for convenience. The caller
1582 can implement their own. All of this following code will get
1583 dead-stripped if QCBORDecode_SetMemPool() is not called.
1584
1585 This is a very primitive memory allocator. It does not track
1586 individual allocations, only a high-water mark. A free or
1587 reallocation must be of the last chunk allocated.
1588
1589 The size of the pool and offset to free memory are packed into the
1590 first 8 bytes of the memory pool so we don't have to keep them in
1591 the decode context. Since the address of the pool may not be
1592 aligned, they have to be packed and unpacked as if they were
1593 serialized data of the wire or such.
1594
1595 The sizes packed in are uint32_t to be the same on all CPU types
1596 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001597 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001598
1599
Laurence Lundbladeee851742020-01-08 08:37:05 -08001600static inline int
1601MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001602{
1603 // Use of UsefulInputBuf is overkill, but it is convenient.
1604 UsefulInputBuf UIB;
1605
Laurence Lundbladeee851742020-01-08 08:37:05 -08001606 // Just assume the size here. It was checked during SetUp so
1607 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001608 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1609 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1610 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1611 return UsefulInputBuf_GetError(&UIB);
1612}
1613
1614
Laurence Lundbladeee851742020-01-08 08:37:05 -08001615static inline int
1616MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001617{
1618 // Use of UsefulOutBuf is overkill, but convenient. The
1619 // length check performed here is useful.
1620 UsefulOutBuf UOB;
1621
1622 UsefulOutBuf_Init(&UOB, Pool);
1623 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1624 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1625 return UsefulOutBuf_GetError(&UOB);
1626}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001627
1628
1629/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001630 Internal function for an allocation, reallocation free and destuct.
1631
1632 Having only one function rather than one each per mode saves space in
1633 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001634
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001635 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1636 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001637static UsefulBuf
1638MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001639{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001640 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001642 uint32_t uPoolSize;
1643 uint32_t uFreeOffset;
1644
1645 if(uNewSize > UINT32_MAX) {
1646 // This allocator is only good up to 4GB. This check should
1647 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1648 goto Done;
1649 }
1650 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1651
1652 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1653 goto Done;
1654 }
1655
1656 if(uNewSize) {
1657 if(pMem) {
1658 // REALLOCATION MODE
1659 // Calculate pointer to the end of the memory pool. It is
1660 // assumed that pPool + uPoolSize won't wrap around by
1661 // assuming the caller won't pass a pool buffer in that is
1662 // not in legitimate memory space.
1663 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1664
1665 // Check that the pointer for reallocation is in the range of the
1666 // pool. This also makes sure that pointer math further down
1667 // doesn't wrap under or over.
1668 if(pMem >= pPool && pMem < pPoolEnd) {
1669 // Offset to start of chunk for reallocation. This won't
1670 // wrap under because of check that pMem >= pPool. Cast
1671 // is safe because the pool is always less than UINT32_MAX
1672 // because of check in QCBORDecode_SetMemPool().
1673 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1674
1675 // Check to see if the allocation will fit. uPoolSize -
1676 // uMemOffset will not wrap under because of check that
1677 // pMem is in the range of the uPoolSize by check above.
1678 if(uNewSize <= uPoolSize - uMemOffset) {
1679 ReturnValue.ptr = pMem;
1680 ReturnValue.len = uNewSize;
1681
1682 // Addition won't wrap around over because uNewSize was
1683 // checked to be sure it is less than the pool size.
1684 uFreeOffset = uMemOffset + uNewSize32;
1685 }
1686 }
1687 } else {
1688 // ALLOCATION MODE
1689 // uPoolSize - uFreeOffset will not underflow because this
1690 // pool implementation makes sure uFreeOffset is always
1691 // smaller than uPoolSize through this check here and
1692 // reallocation case.
1693 if(uNewSize <= uPoolSize - uFreeOffset) {
1694 ReturnValue.len = uNewSize;
1695 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001696 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001697 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001698 }
1699 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001700 if(pMem) {
1701 // FREE MODE
1702 // Cast is safe because of limit on pool size in
1703 // QCBORDecode_SetMemPool()
1704 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1705 } else {
1706 // DESTRUCT MODE
1707 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001708 }
1709 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001710
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001711 UsefulBuf Pool = {pPool, uPoolSize};
1712 MemPool_Pack(Pool, uFreeOffset);
1713
1714Done:
1715 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001716}
1717
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001718
Laurence Lundbladef6531662018-12-04 10:42:22 +09001719/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001720 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001721 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001722QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1723 UsefulBuf Pool,
1724 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001725{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001726 // The pool size and free mem offset are packed into the beginning
1727 // of the pool memory. This compile time check make sure the
1728 // constant in the header is correct. This check should optimize
1729 // down to nothing.
1730 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001731 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001732 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001733
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001734 // The pool size and free offset packed in to the beginning of pool
1735 // memory are only 32-bits. This check will optimize out on 32-bit
1736 // machines.
1737 if(Pool.len > UINT32_MAX) {
1738 return QCBOR_ERR_BUFFER_TOO_LARGE;
1739 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001740
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001741 // This checks that the pool buffer given is big enough.
1742 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1743 return QCBOR_ERR_BUFFER_TOO_SMALL;
1744 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001745
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001746 pMe->StringAllocator.pfAllocator = MemPool_Function;
1747 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1748 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001749
Laurence Lundblade30816f22018-11-10 13:40:22 +07001750 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001751}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001752
Laurence Lundblade1341c592020-04-11 14:19:05 -07001753#include <stdio.h>
1754void printdecode(QCBORDecodeContext *pMe, const char *szName)
1755{
1756 printf("---%s---\nLevel Count Type Offset SaveCount\n", szName);
1757 for(int i = 0; i < 4 /*QCBOR_MAX_ARRAY_NESTING*/; i++) {
1758 const char *szX = (i == DecodeNesting_GetLevel(&(pMe->nesting))) ? "->" : " ";
1759 printf("%s %2d %5d %2d %6u %2d\n",
1760 szX,
1761 i,
1762 pMe->nesting.pMapsAndArrays[i].uCount,
1763 pMe->nesting.pMapsAndArrays[i].uMajorType,
1764 pMe->nesting.pMapsAndArrays[i].uOffset,
1765 pMe->nesting.pMapsAndArrays[i].uSaveCount
1766 );
1767 }
1768 printf("\n");
1769}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001770
1771
1772/*
1773 * Public function. See qcbor_util.h
1774 */
1775static QCBORError
1776ConsumeItem(QCBORDecodeContext *pMe,
1777 const QCBORItem *pItemToConsume,
1778 uint_fast8_t *puNextNestLevel)
1779{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001780 QCBORError nReturn;
1781 QCBORItem Item;
1782
1783 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001784
Laurence Lundblade1341c592020-04-11 14:19:05 -07001785 if(pItemToConsume->uDataType == QCBOR_TYPE_MAP ||
1786 pItemToConsume->uDataType == QCBOR_TYPE_ARRAY) {
1787 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001788
Laurence Lundblade1341c592020-04-11 14:19:05 -07001789 /* This works for definite and indefinite length
1790 * maps and arrays by using the nesting level
1791 */
1792 do {
1793 nReturn = QCBORDecode_GetNext(pMe, &Item);
1794 if(nReturn != QCBOR_SUCCESS) {
1795 goto Done;
1796 }
1797 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001798
Laurence Lundblade1341c592020-04-11 14:19:05 -07001799 if(puNextNestLevel != NULL) {
1800 *puNextNestLevel = Item.uNextNestLevel;
1801 }
1802 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001803
Laurence Lundblade1341c592020-04-11 14:19:05 -07001804 } else {
1805 /* item_to_consume is not a map or array */
1806 if(puNextNestLevel != NULL) {
1807 /* Just pass the nesting level through */
1808 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1809 }
1810 nReturn = QCBOR_SUCCESS;
1811 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001812
1813Done:
1814 return nReturn;
1815}
1816
1817
Laurence Lundblade1341c592020-04-11 14:19:05 -07001818/* Return true if the labels in Item1 and Item2 are the same.
1819 Works only for integer and string labels. Returns false
1820 for any other type. */
1821static inline bool
1822MatchLabel(QCBORItem Item1, QCBORItem Item2)
1823{
1824 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1825 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1826 return true;
1827 }
1828 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
1829 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1830 return true;
1831 }
1832 }
1833 /* Other label types are never matched */
1834 return false;
1835}
1836
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001837/*
1838 * Public function. qcbor_util.h
1839 */
1840QCBORError
1841GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset)
1842{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001843 QCBORItem *pIterator;
1844 QCBORError nReturn;
1845
1846
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001847
Laurence Lundblade1341c592020-04-11 14:19:05 -07001848 printdecode(pMe, "GetItemsInMapStart");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001849
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001850
Laurence Lundblade1341c592020-04-11 14:19:05 -07001851 // TODO: check we are in map mode
1852
1853 /* Clear structure holding the items found */
1854 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1855 pIterator->uDataType = QCBOR_TYPE_NONE;
1856 }
1857
1858 // Save the cursor and such used for pre-order traversal
1859/* const size_t uSave = UsefulInputBuf_Tell(&(pMe->InBuf));
1860 const uint16_t uSaveCount = pMe->nesting.pCurrent->uCount;
1861 struct nesting_decode_level *pSaveCurrent = pMe->nesting.pCurrent;
1862*/
1863 QCBORDecodeNesting N = pMe->nesting;
1864
1865 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1866 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
1867 }
1868
1869 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1870
1871 /* Loop over all the items in the map. They could be
1872 * deeply nested and this should handle both definite
1873 * and indefinite length maps and arrays, so this
1874 * adds some complexity. */
1875 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
1876
1877 while(1) {
1878 QCBORItem Item;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001879
Laurence Lundblade1341c592020-04-11 14:19:05 -07001880 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001881
Laurence Lundblade1341c592020-04-11 14:19:05 -07001882 printdecode(pMe, "GetItemsInMapMid1");
1883
1884 if((nReturn = QCBORDecode_GetNext(pMe, &Item)) != QCBOR_SUCCESS) {
1885 /* Got non-well-formed CBOR */
1886 goto Done;
1887 }
1888
1889 printdecode(pMe, "GetItemsInMapMid2");
1890
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001891
Laurence Lundblade1341c592020-04-11 14:19:05 -07001892 // Loop over all the items to check this item against
1893 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1894 if(MatchLabel(Item, *pIterator)) {
1895 // A label match has been found
1896 if(pIterator->uDataType != QCBOR_TYPE_NONE) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001897 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
1898 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001899 }
1900
1901 /* Successful match. Return the item. */
1902 *pIterator = Item;
1903 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001904 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001905 }
1906 }
1907 }
1908
1909 /* Still have to consume the item that did or didn't match.
1910 The item could be a deeply nested array or map. */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001911
1912 /* Only looking at top-level data items, so just consume any
1913 * map or array encountered.*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07001914 uint_fast8_t uNextNestLevel;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001915
Laurence Lundblade1341c592020-04-11 14:19:05 -07001916 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
1917 if(nReturn) {
1918 goto Done;
1919 }
1920 if(uNextNestLevel < uMapNestLevel) {
1921 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001922 /* Got all the items in the map. This is the non-error exit
1923 * from the loop. */
1924 // Cast OK because encoded CBOR is limited to UINT32_MAX
Laurence Lundblade1341c592020-04-11 14:19:05 -07001925 pMe->uMapEndOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001926 // record the offset here for exit to save CPU time
Laurence Lundblade1341c592020-04-11 14:19:05 -07001927 break;
1928 }
1929 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001930
1931Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07001932 printdecode(pMe, "GetItemsInMapBeforeDone");
1933
1934
1935 // Restore cursor for pre-order traversal
1936 /*
1937 pMe->nesting.pCurrent = pSaveCurrent;
1938 pMe->nesting.pCurrent->uCount = uSaveCount;
1939 UsefulInputBuf_Seek(&(pMe->InBuf), uSave);
1940 */
1941 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001942
Laurence Lundblade1341c592020-04-11 14:19:05 -07001943 printdecode(pMe, "GetItemsInMapEnd");
1944
1945 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001946}
1947
1948void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
1949{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001950 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001951
Laurence Lundblade1341c592020-04-11 14:19:05 -07001952 if(pMe->uMapEndOffset) {
1953 uEndOffset = pMe->uMapEndOffset;
1954 // It is only valid once.
1955 pMe->uMapEndOffset = 0;
1956 } else {
1957 QCBORItem Dummy;
1958
1959 Dummy.uLabelType = QCBOR_TYPE_NONE;
1960
1961 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, &uEndOffset);
1962
1963 (void)nReturn; // TODO:
1964 }
1965
1966 printdecode(pMe, "start exit");
1967 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
1968
1969 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1970 pMe->nesting.pCurrent->uCount = 1;
1971 }
1972 DecodeNesting_DecrementCount(&(pMe->nesting));
1973 printdecode(pMe, "end exit");
1974
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001975}
1976
1977
1978QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07001979 int64_t nLabel,
1980 uint8_t uQcborType,
1981 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001982{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001983 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001984
Laurence Lundblade1341c592020-04-11 14:19:05 -07001985 One[0].uLabelType = QCBOR_TYPE_INT64;
1986 One[0].label.int64 = nLabel;
1987 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
1988
1989 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
1990 if(nReturn) {
1991 return nReturn;
1992 }
1993
1994 if(One[0].uDataType == QCBOR_TYPE_NONE) {
1995 return QCBOR_ERR_NOT_FOUND;
1996 }
1997
1998 if(One[0].uDataType != uQcborType) {
1999 return QCBOR_ERR_UNEXPECTED_TYPE;
2000 }
2001
2002 *pItem = One[0];
2003
2004 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002005}
2006
2007
2008QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002009 const char *szLabel,
2010 uint8_t uQcborType,
2011 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002012{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002013 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002014
Laurence Lundblade1341c592020-04-11 14:19:05 -07002015 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2016 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2017 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2018
2019 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
2020 if(nReturn) {
2021 return nReturn;
2022 }
2023
2024 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2025 return QCBOR_ERR_NOT_FOUND;
2026 }
2027
2028 if(One[0].uDataType != uQcborType) {
2029 return QCBOR_ERR_UNEXPECTED_TYPE;
2030 }
2031
2032 *pItem = One[0];
2033
2034 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002035}
2036
2037
2038void QCBORDecode_GetBstrInMap(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2039{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002040 // TODO: error handling
2041 QCBORItem Item;
2042 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2043 *pBstr = Item.val.string;
2044}
2045
2046void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2047{
2048 // TODO: error handling
2049 QCBORItem Item;
2050 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2051 *pBstr = Item.val.string;
2052}
2053
2054void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2055{
2056 // TODO: error handling
2057 QCBORItem Item;
2058 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2059 *pBstr = Item.val.string;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002060}
2061
2062
2063QCBORError QCBORDecode_EnterMapInMap(QCBORDecodeContext *pMe, int64_t nLabel)
2064{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002065 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002066
Laurence Lundblade1341c592020-04-11 14:19:05 -07002067 One[0].uLabelType = QCBOR_TYPE_INT64;
2068 One[0].label.int64 = nLabel;
2069 One[1].uLabelType = QCBOR_TYPE_NONE;
2070
2071 size_t uOffset;
2072
2073 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2074
2075 if(nReturn) {
2076 return nReturn;
2077 }
2078
2079 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2080 return QCBOR_ERR_UNEXPECTED_TYPE;
2081 }
2082
2083 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2084
2085 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2086
2087 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2088 pMe->nesting.pCurrent->uMapMode = 1;
2089
2090 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002091}
2092
2093
2094QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2095{
2096 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002097
Laurence Lundblade1341c592020-04-11 14:19:05 -07002098 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2099 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2100 One[1].uLabelType = QCBOR_TYPE_NONE;
2101
2102 size_t uOffset;
2103
2104 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2105
2106 if(nReturn) {
2107 return nReturn;
2108 }
2109
2110 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2111 return QCBOR_ERR_UNEXPECTED_TYPE;
2112 }
2113
2114 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2115
2116 QCBORItem MapToEnter;
2117 QCBORDecode_GetNext(pMe, &MapToEnter);
2118
2119
2120 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2121
2122 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2123 pMe->nesting.pCurrent->uMapMode = 1;
2124 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2125
2126 printdecode(pMe, "Entered Map in Map");
2127
2128 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002129}
2130
2131
2132
Laurence Lundblade1341c592020-04-11 14:19:05 -07002133
2134QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2135{
2136 QCBORItem One[2];
2137
2138 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2139 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2140 One[1].uLabelType = QCBOR_TYPE_NONE;
2141
2142 size_t uOffset;
2143
2144 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2145
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002146 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002147 return nReturn;
2148 }
2149
2150 if(One[0].uDataType != QCBOR_TYPE_ARRAY) {
2151 return QCBOR_ERR_UNEXPECTED_TYPE;
2152 }
2153
2154 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2155
2156 QCBORItem ArrayToEnter;
2157 QCBORDecode_GetNext(pMe, &ArrayToEnter);
2158
2159
2160 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2161
2162 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2163 pMe->nesting.pCurrent->uMapMode = 1;
2164 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2165
2166 printdecode(pMe, "Entered Array in Map");
2167
2168 return 0;
2169}
2170
2171
2172
2173
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002174/* Next item must be map or this generates an error */
2175QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2176{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002177 QCBORItem Item;
2178 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002179
2180 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002181 nReturn = QCBORDecode_GetNext(pMe, &Item);
2182 if(nReturn != QCBOR_SUCCESS) {
2183 return nReturn;
2184 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002185 if(Item.uDataType != QCBOR_TYPE_MAP) {
2186 return QCBOR_ERR_UNEXPECTED_TYPE;
2187 }
2188
2189 printdecode(pMe, "EnterMap");
2190
2191 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2192 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2193 pMe->nesting.pCurrent->uMapMode = 1;
2194 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002195
2196
Laurence Lundblade1341c592020-04-11 14:19:05 -07002197 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002198}
2199
2200
2201
2202QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2203{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002204 return GetItemsInMap(pCtx, pItemList, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002205}
2206
2207
2208void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2209{
2210 // TODO: error handling
2211 QCBORItem Item;
2212 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2213 *pInt = Item.val.int64;
2214}
2215
2216
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002218{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002219 // TODO: check for map mode
2220 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2221 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2222}
2223
2224
2225QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2226{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002227 QCBORItem Item;
2228 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002229
2230 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002231 nReturn = QCBORDecode_GetNext(pMe, &Item);
2232 if(nReturn != QCBOR_SUCCESS) {
2233 return nReturn;
2234 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002235 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2236 return QCBOR_ERR_UNEXPECTED_TYPE;
2237 }
2238
2239 printdecode(pMe, "EnterArray");
2240
2241 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2242 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2243 pMe->nesting.pCurrent->uMapMode = 1;
2244 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2245
2246
2247 return QCBOR_SUCCESS;
2248}
2249
2250
2251void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2252{
2253 // TODO: make sure we have entered an array
2254 // TODO: combine with code for map? It is the same so far.
2255 size_t uEndOffset;
2256
2257 if(pMe->uMapEndOffset) {
2258 uEndOffset = pMe->uMapEndOffset;
2259 // It is only valid once.
2260 pMe->uMapEndOffset = 0;
2261 } else {
2262 QCBORItem Dummy;
2263
2264 Dummy.uLabelType = QCBOR_TYPE_NONE;
2265
2266 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, &uEndOffset);
2267
2268 (void)nReturn; // TODO:
2269 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002270
Laurence Lundblade1341c592020-04-11 14:19:05 -07002271 printdecode(pMe, "start exit");
2272 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2273
2274 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2275 pMe->nesting.pCurrent->uCount = 1;
2276 }
2277 DecodeNesting_DecrementCount(&(pMe->nesting));
2278 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002279}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002280
Laurence Lundbladee6430642020-03-14 21:15:44 -07002281
2282
Laurence Lundbladec4537442020-04-14 18:53:22 -07002283void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002284{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002285 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002286 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002287 return;
2288 }
2289
Laurence Lundbladec4537442020-04-14 18:53:22 -07002290 QCBORError nError;
2291 QCBORItem Item;
2292
2293 nError = QCBORDecode_GetNext(pMe, &Item);
2294 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002295 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002296 return;
2297 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002298
2299 switch(Item.uDataType) {
2300 case QCBOR_TYPE_TRUE:
2301 *pValue = true;
2302 break;
2303
2304 case QCBOR_TYPE_FALSE:
2305 *pValue = false;
2306 break;
2307
2308 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002309 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002310 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002311 }
2312}
2313
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002314#if 0
2315// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002316/* Types of text strings
2317 * Plain, b64, b64url, URI, regex, MIME Text
2318 * One function for each with options to expect plain?
2319 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002320 *
2321 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002322 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002323void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002324{
2325 QCBORItem Item;
2326 QCBORError nError;
2327
2328 nError = QCBORDecode_GetNext(pMe, &Item);
2329 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002330 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002331 return;
2332 }
2333
Laurence Lundbladec4537442020-04-14 18:53:22 -07002334 if(pLabel != NULL) {
2335 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002336 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002337 return;
2338 } else {
2339 // TODO: what about label allocation?
2340 pLabel->uLabelType = Item.uLabelType;
2341 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2342 }
2343 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002344
2345 switch(Item.uDataType) {
2346 case QCBOR_TYPE_TEXT_STRING:
2347 *pValue = Item.val.string;
2348 break;
2349
2350 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002351 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002352 }
2353}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002354#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002355
2356
Laurence Lundbladec4537442020-04-14 18:53:22 -07002357/*
2358 Options for MIME data, CBOR, positive big num, negative big num ??
2359 */
2360void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2361{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002362 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002363 // Already in error state, do nothing
2364 return;
2365 }
2366
2367 QCBORError nError;
2368 QCBORItem Item;
2369
2370 nError = QCBORDecode_GetNext(pMe, &Item);
2371 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002372 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002373 return;
2374 }
2375
2376 if(Item.uDataType == uType) {
2377 *pValue = Item.val.string;
2378 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002379 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002380 }
2381}
2382
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002383void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002384{
2385 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2386}
2387
2388
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002389void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002390{
2391 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2392}
2393
2394
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002395void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002396{
2397 // TODO: do these have to be tagged?
2398 // Probably should allow tagged or untagged, but not wrong-tagged
2399 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2400}
2401
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002402void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002403{
2404 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2405}
2406
2407
2408
Laurence Lundbladee6430642020-03-14 21:15:44 -07002409
2410/* Convert a decimal fraction to an int64_t without using
2411 floating point or math libraries. Most decimal fractions
2412 will not fit in an int64_t and this will error out with
2413 under or overflow
2414 */
2415uint8_t Exponentitate10(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
2416{
2417 int64_t nResult;
2418
2419 nResult = nMantissa;
2420
2421 /* This loop will run a maximum of 19 times because
2422 * INT64_MAX < 10 ^^ 19. More than that will cause
Laurence Lundbladec4537442020-04-14 18:53:22 -07002423 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07002424 */
2425 while(nExponent > 0) {
2426 if(nResult > INT64_MAX / 10) {
2427 return 99; // Error overflow
2428 }
2429 nResult = nResult * 10;
2430 nExponent--;
2431 }
2432
2433 while(nExponent < 0 ) {
2434 if(nResult == 0) {
2435 return 98; // Underflow error
2436 }
2437 nResult = nResult / 10;
2438 nExponent--;
2439 }
2440
2441 return 0;
2442}
2443
2444
Laurence Lundbladec4537442020-04-14 18:53:22 -07002445
2446
2447uint8_t Exponentitate10U(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
2448{
2449 uint64_t uResult;
2450
2451 uResult = uMantissa;
2452
2453 /* This loop will run a maximum of 19 times because
2454 * UINT64_MAX < 10 ^^ 19. More than that will cause
2455 * exit with the overflow error
2456 */
2457 while(nExponent > 0) {
2458 if(uResult > UINT64_MAX / 10) {
2459 return 99; // Error overflow
2460 }
2461 uResult = uResult * 10;
2462 nExponent--;
2463 }
2464
2465 while(nExponent < 0 ) {
2466 if(uResult == 0) {
2467 return 98; // Underflow error
2468 }
2469 uResult = uResult / 10;
2470 nExponent--;
2471 }
2472
2473 *puResult = uResult;
2474
2475 return 0;
2476}
2477
2478uint8_t Exponentitate10S(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
2479{
2480 // TODO: is this less code than duplicating the above function?
2481 uint64_t uResult;
2482
2483 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2484
2485 Exponentitate10U(uMantissa, nExponent, &uResult);
2486
2487 if(uResult > INT64_MAX) {
2488 return 99; // Result is too large
2489 } else if(uResult < (uint64_t)-INT64_MIN) {
2490 return 98; // results is too small (large negative number)
2491 }
2492
2493 // TODO: these casts might not work.
2494 *pnResult = nMantissa > 0 ? (int64_t)uResult : (int64_t) -uResult;
2495
2496 return 0;
2497}
2498
2499
2500uint8_t Exponentitate10SS(int64_t nMantissa, int64_t nExponent, uint64_t *puResult)
2501{
2502 if(nMantissa < 0) {
2503 return 77; // can't return a negative result in an unsigned.
2504 }
2505
2506 return Exponentitate10U((uint64_t)nMantissa, nExponent, puResult);
2507}
2508
2509
2510uint8_t Exponentitate10US(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult)
2511{
2512 // TODO: is this less code than duplicating the above function?
2513 uint64_t uResult;
2514
2515 uint8_t uR;
2516
2517 uR = Exponentitate10U(uMantissa, nExponent, &uResult);
2518 if(uR) {
2519 return uR;
2520 }
2521
2522 if(uResult > INT64_MAX) {
2523 return 88;
2524 }
2525 *pnResult = (int64_t)uResult;
2526
2527 return 0;
2528}
2529
2530#include <math.h>
2531
2532uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2533{
2534 // TODO: checkout exceptions; what is HUGE_VAL?
2535 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2536
2537 //if(*pfResult == HUGE_VAL)
2538 return 0;
2539}
2540
2541
Laurence Lundbladee6430642020-03-14 21:15:44 -07002542/* Convert a decimal fraction to an int64_t without using
2543 floating point or math libraries. Most decimal fractions
2544 will not fit in an int64_t and this will error out with
2545 under or overflow
2546 */
2547uint8_t Exponentitate2(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
2548{
2549 int64_t nResult;
2550
2551 nResult = nMantissa;
2552
2553 /* This loop will run a maximum of 19 times because
2554 * INT64_MAX < 2^31. More than that will cause
2555 * exist with the overflow error
2556 */
2557 while(nExponent > 0) {
2558 if(nResult > INT64_MAX << 1) {
2559 return 99; // Error overflow
2560 }
2561 nResult = nResult >> 1;
2562 nExponent--;
2563 }
2564
2565 while(nExponent < 0 ) {
2566 if(nResult == 0) {
2567 return 98; // Underflow error
2568 }
2569 nResult = nResult << 1;
2570 nExponent--;
2571 }
2572
2573 *pnResult = nResult;
2574
2575 return 0;
2576}
2577
2578/*
2579 A) bignum is positive
2580 A1) output is signed INT64_MAX
2581 A2) output is unsigned UINT64_MAX
2582 B) bignum is negative
2583 B1) output is signed INT64_MAX
2584 B2) output is unsigned error
2585 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002586QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002587{
2588 uint64_t nResult;
2589
2590 nResult = 0;
2591 const uint8_t *pByte = BigNum.ptr;
2592 size_t uLen = BigNum.len;
2593 while(uLen--) {
2594 if(nResult > uMax << 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002595 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002596 }
2597 nResult = (nResult >> 8) + *pByte;
2598 }
2599
2600 *pResult = nResult;
2601 return 0;
2602}
2603
Laurence Lundbladec4537442020-04-14 18:53:22 -07002604
2605
2606QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
2607{
2608 double nResult;
2609
2610 nResult = 0;
2611 const uint8_t *pByte = BigNum.ptr;
2612 size_t uLen = BigNum.len;
2613 /* This will overflow and become the float value INFINITY if the number
2614 is too large to fit. No error will be logged.
2615 TODO: should an error be logged? */
2616 while(uLen--) {
2617 nResult = (nResult * 256) + *pByte;
2618 }
2619
2620 *pResult = nResult;
2621 return 0;
2622}
2623
2624
2625QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002626{
2627 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2628}
2629
Laurence Lundbladec4537442020-04-14 18:53:22 -07002630QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002631{
2632 uint64_t uResult;
2633 uint8_t n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
2634 if(n) {
2635 return n;
2636 }
2637 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2638 *pResult = (int64_t)uResult;
2639 return 0;
2640}
2641
2642
Laurence Lundbladec4537442020-04-14 18:53:22 -07002643QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002644{
2645 uint64_t uResult;
2646 uint8_t n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
2647 if(n) {
2648 return n;
2649 }
2650 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2651 *pResult = -(int64_t)uResult;
2652 return 0;
2653}
2654
Laurence Lundbladec4537442020-04-14 18:53:22 -07002655// No function to convert a negative bignum to unsigned; it is an error
2656
2657
2658
Laurence Lundbladee6430642020-03-14 21:15:44 -07002659int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
2660{
2661 int64_t nMantissa;
2662
2663 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2664 if(xx) {
2665 return xx;
2666 }
2667
2668 return Exponentitate10(nMantissa, nExponent, pResult);
2669}
2670
2671
2672
2673#define QCBOR_DECODE_TYPE_INT64 0x01
2674#define QCBOR_DECODE_TYPE_UINT64 0x02
2675#define QCBOR_DECODE_TYPE_FLOAT 0x03
2676#define QCBOR_DECODE_TYPE_BIGFLOAT 0x04
2677#define QCBOR_DECODE_TYPE_DECIMAL_FRACTION 0x05
2678#define QCBOR_DECODE_TYPE_BIG_NUM 0x06
2679
Laurence Lundbladec4537442020-04-14 18:53:22 -07002680
2681/*
2682 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2683 a big float, a decimal fraction or a big num. Conversion will be dones as
2684 expected. Some cases will error out with under or over flow.
2685 */
2686void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002687{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002688 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002689 return;
2690 }
2691
Laurence Lundbladee6430642020-03-14 21:15:44 -07002692 QCBORItem Item;
2693 QCBORError nError;
2694
2695 nError = QCBORDecode_GetNext(pMe, &Item);
2696 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002697 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002698 return;
2699 }
2700
Laurence Lundbladee6430642020-03-14 21:15:44 -07002701 switch(Item.uDataType) {
2702 case QCBOR_TYPE_FLOAT:
2703 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002704 // TODO: what about under/overflow here?
Laurence Lundbladee6430642020-03-14 21:15:44 -07002705 *pValue = (int64_t)Item.val.dfnum;
2706 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002707 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002708 }
2709 break;
2710
2711 case QCBOR_TYPE_INT64:
2712 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2713 *pValue = Item.val.int64;
2714 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002715 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002716 }
2717 break;
2718
2719 case QCBOR_TYPE_UINT64:
2720 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2721 if(Item.val.uint64 < INT64_MAX) {
2722 *pValue = Item.val.int64;
2723 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002724 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002725 }
2726 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002727 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002728 }
2729 break;
2730
Laurence Lundbladec4537442020-04-14 18:53:22 -07002731 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002732 pMe->uLastError = 99; // TODO: fix error code after merge
Laurence Lundbladec4537442020-04-14 18:53:22 -07002733 }
2734}
2735
2736/* This works for signed, unsigned and float */
2737void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2738{
2739 QCBORItem Item;
2740 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2741}
2742
2743
2744
2745/*
2746 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2747 a big float, a decimal fraction or a big num. Conversion will be dones as
2748 expected. Some cases will error out with under or over flow.
2749 */
2750void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2751{
2752 QCBORItem Item;
2753
2754 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2755
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002756 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002757 return;
2758 }
2759
2760 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002761 case QCBOR_TYPE_DECIMAL_FRACTION:
2762 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002763 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002764 Item.val.expAndMantissa.nExponent,
2765 pValue);
2766 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002767 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002768 }
2769 break;
2770
2771 case QCBOR_TYPE_BIGFLOAT:
2772 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002773 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002774 Item.val.expAndMantissa.nExponent,
2775 pValue);
2776 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002777 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002778 }
2779 break;
2780
2781 case QCBOR_TYPE_POSBIGNUM:
2782 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002783 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002784 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002785 pMe->uLastError = 99;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002786 }
2787 break;
2788
2789 case QCBOR_TYPE_NEGBIGNUM:
2790 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002791 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002792 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002793 pMe->uLastError = 99;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002794 }
2795 break;
2796
2797 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2798 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2799 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002800 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2801 if(!pMe->uLastError) {
2802 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002803 Item.val.expAndMantissa.nExponent,
2804 pValue);
2805 }
2806 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002807 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002808 }
2809 break;
2810
2811 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2812 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2813 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002814 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2815 if(!pMe->uLastError) {
2816 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002817 Item.val.expAndMantissa.nExponent,
2818 pValue);
2819 }
2820 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002821 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002822 }
2823 break;
2824
2825 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
2826 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2827 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002828 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2829 if(!pMe->uLastError) {
2830 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002831 Item.val.expAndMantissa.nExponent,
2832 pValue);
2833 }
2834 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002835 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002836 }
2837 break;
2838
2839 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
2840 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2841 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002842 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2843 if(!pMe->uLastError) {
2844 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002845 Item.val.expAndMantissa.nExponent,
2846 pValue);
2847 }
2848 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002849 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002850 }
2851 break;
2852 }
2853}
2854
Laurence Lundbladec4537442020-04-14 18:53:22 -07002855
2856
2857void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
2858{
2859 QCBORItem Item;
2860 QCBORError nError;
2861
2862 nError = QCBORDecode_GetNext(pMe, &Item);
2863 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002864 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002865 return;
2866 }
2867
2868 switch(Item.uDataType) {
2869 case QCBOR_TYPE_FLOAT:
2870 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
2871 if(Item.val.dfnum >= 0) {
2872 *pValue = (uint64_t)Item.val.dfnum;
2873 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002874 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002875 }
2876 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002877 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002878 }
2879 break;
2880
2881 case QCBOR_TYPE_INT64:
2882 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2883 if(Item.val.int64 >= 0) {
2884 *pValue = (uint64_t)Item.val.int64;
2885 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002886 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002887 }
2888 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002889 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002890 }
2891 break;
2892
2893 case QCBOR_TYPE_UINT64:
2894 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2895 *pValue = Item.val.uint64;
2896 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002897 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002898 }
2899 break;
2900 }
2901}
2902
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002903#if 0
2904void QCBORDecode_GetUInt64X(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002905{
2906 QCBORItem Item;
2907 QCBORError nError;
2908
2909 nError = QCBORDecode_GetNext(pMe, &Item);
2910 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002911 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002912 return;
2913 }
2914
Laurence Lundbladee6430642020-03-14 21:15:44 -07002915 switch(Item.uDataType) {
2916 case QCBOR_TYPE_FLOAT:
2917 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
2918 *pValue = (uint64_t)Item.val.dfnum;
2919 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002920 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002921 }
2922 break;
2923
2924 case QCBOR_TYPE_INT64:
2925 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2926 if(Item.val.int64 >= 0) {
2927 *pValue = (uint64_t)Item.val.int64;
2928 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002929 pMe->uLastError = 49; // negative
Laurence Lundbladee6430642020-03-14 21:15:44 -07002930 }
2931 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002932 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002933 }
2934 break;
2935
2936 case QCBOR_TYPE_UINT64:
2937 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2938 *pValue = Item.val.uint64;
2939 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002940 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002941 }
2942 break;
2943
2944 case QCBOR_TYPE_DECIMAL_FRACTION:
2945 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002946 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002947 Item.val.expAndMantissa.nExponent,
2948 pValue);
2949 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002950 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002951 }
2952 break;
2953
2954 case QCBOR_TYPE_BIGFLOAT:
2955 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002956 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002957 Item.val.expAndMantissa.nExponent,
2958 pValue);
2959 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002960 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002961 }
2962 break;
2963
2964 case QCBOR_TYPE_POSBIGNUM:
2965 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002966 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002967 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002968 pMe->uLastError = 99;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002969 }
2970 break;
2971
2972 case QCBOR_TYPE_NEGBIGNUM:
2973 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002974 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002975 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002976 pMe->uLastError = 99;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002977 }
2978 break;
2979
2980 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2981 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2982 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002983 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2984 if(!pMe->uLastError) {
2985 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002986 Item.val.expAndMantissa.nExponent,
2987 pValue);
2988 }
2989 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002990 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07002991 }
2992 break;
2993
2994 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2995 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2996 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002997 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2998 if(!pMe->uLastError) {
2999 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003000 Item.val.expAndMantissa.nExponent,
3001 pValue);
3002 }
3003 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003004 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003005 }
3006 break;
3007
3008 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3009 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3010 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003011 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3012 if(!pMe->uLastError) {
3013 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003014 Item.val.expAndMantissa.nExponent,
3015 pValue);
3016 }
3017 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003018 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003019 }
3020 break;
3021
3022 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3023 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3024 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003025 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3026 if(!pMe->uLastError) {
3027 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003028 Item.val.expAndMantissa.nExponent,
3029 pValue);
3030 }
3031 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003032 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003033 }
3034 break;
3035 }
3036}
3037
Laurence Lundbladec4537442020-04-14 18:53:22 -07003038
3039/*
3040
3041 Convert from bignums,
3042
3043 */
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003044void QCBORDecode_GetDouble(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003045{
3046 /* the same range of conversions */
3047
Laurence Lundbladec4537442020-04-14 18:53:22 -07003048 /* Conversion from bignums, decimal fractions and such will be interesting */
3049
3050 QCBORItem Item;
3051 QCBORError nError;
3052
3053 nError = QCBORDecode_GetNext(pMe, &Item);
3054 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003055 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003056 return;
3057 }
3058
Laurence Lundbladec4537442020-04-14 18:53:22 -07003059
3060 switch(Item.uDataType) {
3061 case QCBOR_TYPE_FLOAT:
3062 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3063 *pValue = Item.val.dfnum;
3064 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003065 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003066 }
3067 break;
3068
3069 case QCBOR_TYPE_INT64:
3070 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3071 // TODO: how does this work?
3072 *pValue = (double)Item.val.int64;
3073 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003074 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003075 }
3076 break;
3077
3078 case QCBOR_TYPE_UINT64:
3079 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3080 *pValue = (double)Item.val.uint64;
3081 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003082 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003083 }
3084 break;
3085
3086 case QCBOR_TYPE_DECIMAL_FRACTION:
3087 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003088 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003089 Item.val.expAndMantissa.nExponent,
3090 pValue);
3091 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003092 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003093 }
3094 break;
3095
3096 case QCBOR_TYPE_BIGFLOAT:
3097 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003098 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003099 Item.val.expAndMantissa.nExponent,
3100 pValue);
3101 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003102 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003103 }
3104 break;
3105
3106 case QCBOR_TYPE_POSBIGNUM:
3107 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003108 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003109 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003110 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003111 }
3112 break;
3113
3114 case QCBOR_TYPE_NEGBIGNUM:
3115 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003116 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003117 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003118 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003119 }
3120 break;
3121
3122 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3123 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3124 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003125 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3126 if(!pMe->uLastError) {
3127 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003128 Item.val.expAndMantissa.nExponent,
3129 pValue);
3130 }
3131 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003132 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003133 }
3134 break;
3135
3136 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3137 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3138 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003139 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3140 if(!pMe->uLastError) {
3141 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003142 Item.val.expAndMantissa.nExponent,
3143 pValue);
3144 }
3145 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003146 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003147 }
3148 break;
3149
3150 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3151 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3152 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003153 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3154 if(!pMe->uLastError) {
3155 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003156 Item.val.expAndMantissa.nExponent,
3157 pValue);
3158 }
3159 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003160 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003161 }
3162 break;
3163
3164 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3165 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3166 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003167 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3168 if(!pMe->uLastError) {
3169 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003170 Item.val.expAndMantissa.nExponent,
3171 pValue);
3172 }
3173 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003174 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003175 }
3176 break;
3177 }
3178
3179
3180
Laurence Lundbladee6430642020-03-14 21:15:44 -07003181}
3182
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003183#endif