126 lines
2.5 KiB
C
126 lines
2.5 KiB
C
/*
|
|
* This file has been copied from the cddl-gen submodule.
|
|
* Commit 9f77837f9950da1633d22abf6181a830521a6688
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "cbor_common.h"
|
|
|
|
_Static_assert((sizeof(size_t) == sizeof(void *)),
|
|
"This code needs size_t to be the same length as pointers.");
|
|
|
|
bool new_backup(cbor_state_t *state, uint32_t new_elem_count)
|
|
{
|
|
if ((state->backups->current_backup + 1)
|
|
>= state->backups->num_backups) {
|
|
FAIL();
|
|
}
|
|
|
|
uint32_t i = ++(state->backups->current_backup);
|
|
memcpy(&state->backups->backup_list[i], state,
|
|
sizeof(cbor_state_t));
|
|
|
|
state->elem_count = new_elem_count;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool restore_backup(cbor_state_t *state, uint32_t flags,
|
|
uint32_t max_elem_count)
|
|
{
|
|
const uint8_t *payload = state->payload;
|
|
const uint32_t elem_count = state->elem_count;
|
|
|
|
if (state->backups->current_backup == 0) {
|
|
FAIL();
|
|
}
|
|
|
|
if (flags & FLAG_RESTORE) {
|
|
uint32_t i = state->backups->current_backup;
|
|
|
|
memcpy(state, &state->backups->backup_list[i],
|
|
sizeof(cbor_state_t));
|
|
}
|
|
|
|
if (flags & FLAG_DISCARD) {
|
|
state->backups->current_backup--;
|
|
}
|
|
|
|
if (elem_count > max_elem_count) {
|
|
cbor_print("elem_count: %d (expected max %d)\r\n",
|
|
elem_count, max_elem_count);
|
|
FAIL();
|
|
}
|
|
|
|
if (flags & FLAG_TRANSFER_PAYLOAD) {
|
|
state->payload = payload;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool union_start_code(cbor_state_t *state)
|
|
{
|
|
if (!new_backup(state, state->elem_count)) {
|
|
FAIL();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool union_elem_code(cbor_state_t *state)
|
|
{
|
|
if (!restore_backup(state, FLAG_RESTORE, state->elem_count)) {
|
|
FAIL();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool union_end_code(cbor_state_t *state)
|
|
{
|
|
if (!restore_backup(state, FLAG_DISCARD, state->elem_count)) {
|
|
FAIL();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool entry_function(const uint8_t *payload, uint32_t payload_len,
|
|
const void *struct_ptr, uint32_t *payload_len_out,
|
|
cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups)
|
|
{
|
|
cbor_state_t state = {
|
|
.payload = payload,
|
|
.payload_end = payload + payload_len,
|
|
.elem_count = elem_count,
|
|
};
|
|
|
|
cbor_state_t state_backups[num_backups + 1];
|
|
|
|
cbor_state_backups_t backups = {
|
|
.backup_list = state_backups,
|
|
.current_backup = 0,
|
|
.num_backups = num_backups + 1,
|
|
};
|
|
|
|
state.backups = &backups;
|
|
|
|
bool result = func(&state, struct_ptr);
|
|
|
|
if (result && (payload_len_out != NULL)) {
|
|
*payload_len_out = MIN(payload_len,
|
|
(size_t)state.payload - (size_t)payload);
|
|
}
|
|
return result;
|
|
}
|