Skip to content

Commit

Permalink
zcbor.py: Add support for unordered maps in generated code
Browse files Browse the repository at this point in the history
Signed-off-by: Øyvind Rønningstad <[email protected]>
  • Loading branch information
oyvindronningstad committed Apr 30, 2024
1 parent 635a1f2 commit 10152df
Show file tree
Hide file tree
Showing 16 changed files with 493 additions and 68 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ usage: zcbor code [-h] -c CDDL [--no-prelude] [-v]
ENTRY_TYPES [ENTRY_TYPES ...] [-d] [-e] [--time-header]
[--git-sha-header] [-b {32,64}]
[--include-prefix INCLUDE_PREFIX] [-s]
[--file-header FILE_HEADER]
[--file-header FILE_HEADER] [--unordered-maps]
Parse a CDDL file and produce C code that validates and xcodes CBOR.
The output from this script is a C file and a header file. The header file
Expand Down Expand Up @@ -525,6 +525,10 @@ options:
generated files, e.g. copyright. Can be a string or a
path to a file. If interpreted as a path to an
existing file, the file's contents will be used.
--unordered-maps Add support in the generated code for parsing maps
with unknown element order. This places restrictions
on the level of ambiguity allowed between map keys in
a map.
```

Expand Down
4 changes: 2 additions & 2 deletions include/zcbor_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
*/
int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
size_t n_states, size_t elem_count);
size_t n_states, size_t elem_count, size_t n_flags);

#ifdef ZCBOR_STOP_ON_ERROR
/** Check stored error and fail if present, but only if stop_on_error is true.
Expand Down Expand Up @@ -514,7 +514,7 @@ static inline size_t zcbor_flags_to_states(size_t num_flags)
#define ZCBOR_FLAG_STATES(n_flags) zcbor_flags_to_states(n_flags)

#else
#define ZCBOR_FLAG_STATES(n_flags) 0
#define ZCBOR_FLAG_STATES(n_flags) (n_flags * 0)
#endif

size_t strnlen(const char *, size_t);
Expand Down
1 change: 1 addition & 0 deletions samples/pet/pet.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ target_include_directories(pet PUBLIC
${CMAKE_CURRENT_LIST_DIR}/../../include
${CMAKE_CURRENT_LIST_DIR}/include
)
target_compile_definitions(pet PUBLIC ZCBOR_MAP_SMART_SEARCH)
8 changes: 6 additions & 2 deletions samples/pet/src/pet_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#error "The type file was generated with a different default_max_qty than this file"
#endif





static bool decode_Pet(zcbor_state_t *state, struct Pet *result);


Expand Down Expand Up @@ -52,8 +56,8 @@ int cbor_decode_Pet(
struct Pet *result,
size_t *payload_len_out)
{
zcbor_state_t states[4];
zcbor_state_t states[4 + 0];

return zcbor_entry_function(payload, payload_len, (void *)result, payload_len_out, states,
(zcbor_decoder_t *)decode_Pet, sizeof(states) / sizeof(zcbor_state_t), 1);
(zcbor_decoder_t *)decode_Pet, sizeof(states) / sizeof(zcbor_state_t), 1, 0);
}
8 changes: 6 additions & 2 deletions samples/pet/src/pet_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#error "The type file was generated with a different default_max_qty than this file"
#endif





static bool encode_Pet(zcbor_state_t *state, const struct Pet *input);


Expand Down Expand Up @@ -53,8 +57,8 @@ int cbor_encode_Pet(
const struct Pet *input,
size_t *payload_len_out)
{
zcbor_state_t states[4];
zcbor_state_t states[4 + 0];

return zcbor_entry_function(payload, payload_len, (void *)input, payload_len_out, states,
(zcbor_decoder_t *)encode_Pet, sizeof(states) / sizeof(zcbor_state_t), 1);
(zcbor_decoder_t *)encode_Pet, sizeof(states) / sizeof(zcbor_state_t), 1, 0);
}
8 changes: 6 additions & 2 deletions src/zcbor_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,13 @@ size_t zcbor_header_len_ptr(const void *const value, size_t value_len)

int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
size_t n_states, size_t elem_count)
size_t n_states, size_t elem_count, size_t n_flags)
{
zcbor_new_state(state, n_states, payload, payload_len, elem_count, NULL, 0);
zcbor_new_state(state, n_states, payload, payload_len, elem_count,
(uint8_t *)&state[n_states - 1 - ZCBOR_FLAG_STATES(n_flags)],
ZCBOR_FLAG_STATES(n_flags) * sizeof(zcbor_state_t));

state->constant_state->manually_process_elem = true;

bool ret = func(state, result);

Expand Down
14 changes: 6 additions & 8 deletions tests/cases/serial_recovery.cddl
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
; SPDX-License-Identifier: Apache-2.0
;

Member = ("image" => int) /
("data" => bstr) /
("len" => int) /
("off" => int) /
("sha" => bstr) /
(tstr => any)

Upload = {
3*8members: Member
? "image" => uint,
? "len" => uint,
"off" => uint,
? "sha" => bstr,
? "data" => bstr,
? "upgrade" => bool,
}
36 changes: 36 additions & 0 deletions tests/cases/unordered_map.cddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
;
; Copyright (c) 2023 Nordic Semiconductor ASA
;
; SPDX-License-Identifier: Apache-2.0
;

UnorderedMap1 = {
1 => "one",
2 => "two",
int => bstr,
"foo" => "bar",
bazboz,
*bstr => intlist,
}

bazboz = ("baz" => "boz")
intlist = [*int]

UnorderedMap2 = {
+typeUnion,
"map" => {
?-1 => bstr,
?-2 => bstr,
?bool => int,
}
}

typeUnion = type1 / type2 / typeDefault
type1 = 1 => tstr
type2 = 2 => tstr
typeDefault = int => nil

UnorderedMap3 = {
1*2000 uint => uint,
1*2000 nint => nint,
}
1 change: 1 addition & 0 deletions tests/decode/test3_simple/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ set(py_command_serial_recovery
-d
${bit_arg}
--short-names
--unordered-maps

# Testing the --include-prefix option
--include-prefix serial
Expand Down
43 changes: 18 additions & 25 deletions tests/decode/test3_simple/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,19 +487,15 @@ ZTEST(cbor_decode_test3, test_serial1)
zassert_equal(ZCBOR_SUCCESS, ret, "decoding failed: %d.", ret);
zassert_equal(sizeof(serial_rec_input1), decode_len, NULL);

zassert_equal(5, upload.members_count,
"expect 5 members");
zassert_equal(Member_data_c, upload.members[0].members
.Member_choice, "expect data 1st");
zassert_equal(Member_image_c, upload.members[1].members
.Member_choice, "expect image 2nd");
zassert_equal(Member_len_c, upload.members[2].members
.Member_choice, "was %d\r\n", upload.members[2].members
.Member_choice);
zassert_equal(Member_off_c, upload.members[3].members
.Member_choice, "expect off 4th");
zassert_equal(Member_sha_c, upload.members[4].members
.Member_choice, "expect sha 5th");
zassert_true(upload.data_present, NULL);
zassert_equal(0x129, upload.data.data.len, NULL);
zassert_true(upload.image_present, NULL);
zassert_equal(0, upload.image.image, NULL);
zassert_true(upload.len_present, NULL);
zassert_equal(0x3b2c, upload.len.len, NULL);
zassert_equal(0, upload.off, NULL);
zassert_true(upload.sha_present, NULL);
zassert_equal(0x20, upload.sha.sha.len, NULL);
}

ZTEST(cbor_decode_test3, test_serial2)
Expand All @@ -511,18 +507,15 @@ ZTEST(cbor_decode_test3, test_serial2)
zassert_equal(ZCBOR_SUCCESS, ret, "decoding failed: %d.", ret);
zassert_equal(sizeof(serial_rec_input2), decode_len, NULL);

zassert_equal(5, upload.members_count,
"expect 5 members");
zassert_equal(Member_data_c, upload.members[0].members
.Member_choice, "expect data 1st");
zassert_equal(Member_image_c, upload.members[1].members
.Member_choice, "expect image 2nd");
zassert_equal(Member_len_c, upload.members[2].members
.Member_choice, "expect len 3rd");
zassert_equal(Member_off_c, upload.members[3].members
.Member_choice, "expect off 4th");
zassert_equal(Member_sha_c, upload.members[4].members
.Member_choice, "expect sha 5th");
zassert_true(upload.data_present, NULL);
zassert_equal(0x129, upload.data.data.len, NULL);
zassert_true(upload.image_present, NULL);
zassert_equal(0, upload.image.image, NULL);
zassert_true(upload.len_present, NULL);
zassert_equal(0x2fe0, upload.len.len, NULL);
zassert_equal(0, upload.off, NULL);
zassert_true(upload.sha_present, NULL);
zassert_equal(0x20, upload.sha.sha.len, NULL);
}

ZTEST_SUITE(cbor_decode_test3, NULL, NULL, NULL, NULL, NULL);
2 changes: 2 additions & 0 deletions tests/decode/test9_manifest14/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cmake_minimum_required(VERSION 3.13.1)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(test9_manifest14)
set(MAP_SEARCH_FLAGS ON) # Because of --unordered maps
include(../../cmake/test_template.cmake)

if (NOT MANIFEST)
Expand All @@ -30,6 +31,7 @@ set(py_command
SUIT_Common_Sequence
-d
${bit_arg}
--unordered-maps
)

execute_process(
Expand Down
39 changes: 39 additions & 0 deletions tests/decode/testA_unordered_map/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#

cmake_minimum_required(VERSION 3.13.1)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(test9_manifest14)
set(MAP_SEARCH_FLAGS ON) # Because of --unordered maps
set(MAP_SMART_SEARCH ON)
include(../../cmake/test_template.cmake)

set(py_command
${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_LIST_DIR}/../../../zcbor/zcbor.py
code
-c ${CMAKE_CURRENT_LIST_DIR}/../../cases/unordered_map.cddl
--output-cmake ${PROJECT_BINARY_DIR}/unordered_map.cmake
-t
UnorderedMap1
UnorderedMap2
UnorderedMap3
-d
${bit_arg}
--unordered-maps
)

execute_process(
COMMAND
${py_command}
COMMAND_ERROR_IS_FATAL ANY
)

include(${PROJECT_BINARY_DIR}/unordered_map.cmake)

target_link_libraries(unordered_map PRIVATE zephyr_interface)
target_link_libraries(app PRIVATE unordered_map)
8 changes: 8 additions & 0 deletions tests/decode/testA_unordered_map/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#

CONFIG_ZTEST=y
CONFIG_ZTEST_STACK_SIZE=131072
Loading

0 comments on commit 10152df

Please sign in to comment.