Prototype simple map decoder
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 4c641ae..44e11fd 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -923,6 +923,19 @@
QCBORError QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+typedef QCBORError (*MapCB)(void *pCBCtx, QCBORDecodeContext *pDecodeCtx, QCBORItem *pDecodedItem);
+
+typedef struct {
+ int64_t nLabel;
+ uint8_t uType;
+ MapCB pCB;
+} MCB;
+
+
+QCBORError QCBORDecode_Mappie(QCBORDecodeContext *pCtx, uint16_t uMapSize, const MCB *pCBList, void *pCBCtx, UsefulBuf DupDetectionBuffer);
+
+
/**
* @brief Get the next item, fully consuming it if it is a map or array.
*
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 8217073..4b6fbd2 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -2811,6 +2811,74 @@
}
+QCBORError
+QCBORDecode_Mappie(QCBORDecodeContext *pMe,
+ const uint16_t uMapSize,
+ const MCB *pCBList,
+ void *pCBCtx,
+ const UsefulBuf DupDetection)
+{
+ QCBORItem Item;
+ QCBORError uErr;
+
+ if(!UsefulBuf_IsNULL(DupDetection)) {
+ if(DupDetection.len < uMapSize * sizeof(int64_t)) {
+ /* Dup detection buffer too small*/
+ return 888;
+ }
+ }
+
+ /* Loop over items */
+ for(int xx = 0; xx< uMapSize; xx++) {
+ uErr = QCBORDecode_GetNext(pMe, &Item);
+ if(uErr) {
+ goto Done;
+ }
+
+ if(Item.uLabelType != QCBOR_TYPE_INT64) {
+ /* Only works on integer labels */
+ // TODO: proper error code
+ return 99;
+ }
+
+ /* Duplicate detection if caller supplied a buffer */
+ if(!UsefulBuf_IsNULL(DupDetection)) {
+ for(int j = 0; j < xx; j++) {
+ if(((int64_t *)DupDetection.ptr)[xx] == Item.label.int64) {
+ /* Found a duplicate */
+ return 777;
+ }
+ }
+
+ ((int64_t *)DupDetection.ptr)[xx] = Item.label.int64;
+ }
+
+ /* Loop over CB's looking for label */
+ for(int i = 0 ; pCBList[i].pCB != NULL; i++) {
+
+ if(pCBList[i].nLabel == Item.label.int64) {
+ if(pCBList[i].uType != Item.uDataType &&
+ pCBList[i].uType != QCBOR_TYPE_ANY) {
+ uErr = QCBOR_ERR_UNEXPECTED_TYPE;
+ goto Done;
+ }
+
+ /* Matched label, make call back */
+ uErr = (*pCBList[i].pCB)(pCBCtx, pMe, &Item);
+ if(uErr) {
+ goto Done;
+ }
+ break; /* First callback for label wins */
+ }
+ }
+ }
+ uErr = QCBOR_SUCCESS;
+
+Done:
+ return uErr;
+}
+
+
/* Call only on maps and arrays. Rewinds the cursor
* to the start as if it was just entered.
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index edb0861..8e4212f 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -6070,7 +6070,7 @@
uCBORError = QCBORDecode_Finish(&DCtx);
- return uCBORError;
+ return (int32_t)uCBORError;
}
int32_t CBORSequenceDecodeTests(void)
@@ -7901,3 +7901,82 @@
return 0;
}
+
+
+
+/*
+ {1: "hi", 2: 42, 3: 3.14}
+ */
+
+static const uint8_t spMappieT[] = {0xA3, 0x01, 0x62, 0x68, 0x69, 0x02, 0x18, 0x2A, 0x03, 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F};
+
+struct MappieTest {
+ UsefulBufC Text;
+ int64_t Int;
+ double Float;
+};
+
+
+
+static QCBORError
+DecodeOne(void *pCBCtx, QCBORDecodeContext *pDCtx, QCBORItem *Item)
+{
+ struct MappieTest *pMt = (struct MappieTest *)pCBCtx;
+
+ pMt->Text = Item->val.string;
+
+ return 0;
+}
+
+static QCBORError
+DecodeTwo(void *pCBCtx, QCBORDecodeContext *pDCtx, QCBORItem *Item)
+{
+ struct MappieTest *pMt = (struct MappieTest *)pCBCtx;
+
+ pMt->Int = Item->val.int64;
+
+ return 0;
+}
+
+static QCBORError
+DecodeThree(void *pCBCtx, QCBORDecodeContext *pDCtx, QCBORItem *Item)
+{
+ struct MappieTest *pMt = (struct MappieTest *)pCBCtx;
+
+ pMt->Float = Item->val.dfnum;
+
+ return 0;
+}
+
+
+int32_t MappieTest(void)
+{
+ QCBORDecodeContext DC;
+ QCBORItem Item;
+ QCBORError uErr;
+ MakeUsefulBufOnStack(DupDetect, (sizeof(int64_t) * 4));
+
+ struct MappieTest MT;
+
+ MCB MM[] = {
+ {1, QCBOR_TYPE_TEXT_STRING, &DecodeOne},
+ {2, QCBOR_TYPE_INT64, &DecodeTwo},
+ {3, QCBOR_TYPE_DOUBLE, &DecodeThree},
+ {0, QCBOR_TYPE_NONE, NULL}
+ };
+
+
+ QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spMappieT), 0);
+
+ QCBORDecode_GetNext(&DC, &Item);
+
+ uErr = QCBORDecode_Mappie(&DC, Item.val.uCount, MM, &MT, DupDetect);
+
+ uErr = QCBORDecode_Finish(&DC);
+
+ if(MT.Int != 42) {
+ return 99;
+ }
+
+ return 0;
+}
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 11fdc94..847039c 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -318,4 +318,9 @@
*/
int32_t CBORTestIssue134(void);
+
+
+int32_t MappieTest(void);
+
+
#endif /* defined(__QCBOR__qcbort_decode_tests__) */
diff --git a/test/run_tests.c b/test/run_tests.c
index 54cd883..b471731 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -66,6 +66,7 @@
static test_entry s_tests[] = {
+ TEST_ENTRY(MappieTest),
TEST_ENTRY(OpenCloseBytesTest),
TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),