Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype simple map decoder #138

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions inc/qcbor/qcbor_decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,19 @@ void QCBORDecode_VGetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
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.
*
Expand Down
68 changes: 68 additions & 0 deletions src/qcbor_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2811,6 +2811,74 @@ void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedIte
}


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.
Expand Down
81 changes: 80 additions & 1 deletion test/qcbor_decode_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -6070,7 +6070,7 @@ int32_t CBORTestIssue134()

uCBORError = QCBORDecode_Finish(&DCtx);

return uCBORError;
return (int32_t)uCBORError;
}

int32_t CBORSequenceDecodeTests(void)
Expand Down Expand Up @@ -7901,3 +7901,82 @@ int32_t BoolTest(void)

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;
}
5 changes: 5 additions & 0 deletions test/qcbor_decode_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,9 @@ Test GitHub issue #134: decode an indefinite-length string with a zero-length fi
*/
int32_t CBORTestIssue134(void);



int32_t MappieTest(void);


#endif /* defined(__QCBOR__qcbort_decode_tests__) */
1 change: 1 addition & 0 deletions test/run_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static test_entry2 s_tests2[] = {


static test_entry s_tests[] = {
TEST_ENTRY(MappieTest),
TEST_ENTRY(OpenCloseBytesTest),
TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),
Expand Down