1 /*
2 * This file has been copied from the cddl-gen submodule.
3 * Commit 9f77837f9950da1633d22abf6181a830521a6688
4 */
5
6 /*
7 * Copyright (c) 2020 Nordic Semiconductor ASA
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <stddef.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <string.h>
16 #include "cbor_common.h"
17
18 _Static_assert((sizeof(size_t) == sizeof(void *)),
19 "This code needs size_t to be the same length as pointers.");
20
new_backup(cbor_state_t * state,uint32_t new_elem_count)21 bool new_backup(cbor_state_t *state, uint32_t new_elem_count)
22 {
23 if ((state->backups->current_backup + 1)
24 >= state->backups->num_backups) {
25 FAIL();
26 }
27
28 uint32_t i = ++(state->backups->current_backup);
29 memcpy(&state->backups->backup_list[i], state,
30 sizeof(cbor_state_t));
31
32 state->elem_count = new_elem_count;
33
34 return true;
35 }
36
37
restore_backup(cbor_state_t * state,uint32_t flags,uint32_t max_elem_count)38 bool restore_backup(cbor_state_t *state, uint32_t flags,
39 uint32_t max_elem_count)
40 {
41 const uint8_t *payload = state->payload;
42 const uint32_t elem_count = state->elem_count;
43
44 if (state->backups->current_backup == 0) {
45 FAIL();
46 }
47
48 if (flags & FLAG_RESTORE) {
49 uint32_t i = state->backups->current_backup;
50
51 memcpy(state, &state->backups->backup_list[i],
52 sizeof(cbor_state_t));
53 }
54
55 if (flags & FLAG_DISCARD) {
56 state->backups->current_backup--;
57 }
58
59 if (elem_count > max_elem_count) {
60 cbor_print("elem_count: %d (expected max %d)\r\n",
61 elem_count, max_elem_count);
62 FAIL();
63 }
64
65 if (flags & FLAG_TRANSFER_PAYLOAD) {
66 state->payload = payload;
67 }
68
69 return true;
70 }
71
72
union_start_code(cbor_state_t * state)73 bool union_start_code(cbor_state_t *state)
74 {
75 if (!new_backup(state, state->elem_count)) {
76 FAIL();
77 }
78 return true;
79 }
80
81
union_elem_code(cbor_state_t * state)82 bool union_elem_code(cbor_state_t *state)
83 {
84 if (!restore_backup(state, FLAG_RESTORE, state->elem_count)) {
85 FAIL();
86 }
87 return true;
88 }
89
union_end_code(cbor_state_t * state)90 bool union_end_code(cbor_state_t *state)
91 {
92 if (!restore_backup(state, FLAG_DISCARD, state->elem_count)) {
93 FAIL();
94 }
95 return true;
96 }
97
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)98 bool entry_function(const uint8_t *payload, uint32_t payload_len,
99 const void *struct_ptr, uint32_t *payload_len_out,
100 cbor_encoder_t func, uint32_t elem_count, uint32_t num_backups)
101 {
102 cbor_state_t state = {
103 .payload = payload,
104 .payload_end = payload + payload_len,
105 .elem_count = elem_count,
106 };
107
108 cbor_state_t state_backups[num_backups + 1];
109
110 cbor_state_backups_t backups = {
111 .backup_list = state_backups,
112 .current_backup = 0,
113 .num_backups = num_backups + 1,
114 };
115
116 state.backups = &backups;
117
118 bool result = func(&state, struct_ptr);
119
120 if (result && (payload_len_out != NULL)) {
121 *payload_len_out = MIN(payload_len,
122 (size_t)state.payload - (size_t)payload);
123 }
124 return result;
125 }
126