1 /*
2 * Copyright (c) 2022-2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <errno.h>
9
10 #include <zcbor_common.h>
11 #include <zcbor_decode.h>
12
13 #include <mgmt/mcumgr/util/zcbor_bulk.h>
14
zcbor_map_decode_bulk(zcbor_state_t * zsd,struct zcbor_map_decode_key_val * map,size_t map_size,size_t * matched)15 int zcbor_map_decode_bulk(zcbor_state_t *zsd, struct zcbor_map_decode_key_val *map,
16 size_t map_size, size_t *matched)
17 {
18 bool ok;
19 struct zcbor_map_decode_key_val *dptr = map;
20
21 if (!zcbor_map_start_decode(zsd)) {
22 return -EBADMSG;
23 }
24
25 *matched = 0;
26 ok = true;
27
28 do {
29 struct zcbor_string key;
30 bool found = false;
31 size_t map_count = 0;
32
33 ok = zcbor_tstr_decode(zsd, &key);
34
35 while (ok && map_count < map_size) {
36 if (dptr >= (map + map_size)) {
37 dptr = map;
38 }
39
40 if (key.len == dptr->key.len &&
41 memcmp(key.value, dptr->key.value, key.len) == 0) {
42
43 if (dptr->found) {
44 return -EADDRINUSE;
45 }
46 if (!dptr->decoder(zsd, dptr->value_ptr)) {
47 /* Failure to decode value matched to key
48 * means that either decoder has been
49 * incorrectly assigned or SMP payload
50 * is broken anyway.
51 */
52 return -ENOMSG;
53 }
54
55 dptr->found = true;
56 found = true;
57 ++dptr;
58 ++(*matched);
59 break;
60 }
61
62 ++dptr;
63 ++map_count;
64 }
65
66 if (!found && ok) {
67 ok = zcbor_any_skip(zsd, NULL);
68 }
69 } while (ok);
70
71 return zcbor_map_end_decode(zsd) ? 0 : -EBADMSG;
72 }
73
zcbor_map_decode_bulk_key_found(struct zcbor_map_decode_key_val * map,size_t map_size,const char * key)74 bool zcbor_map_decode_bulk_key_found(struct zcbor_map_decode_key_val *map, size_t map_size,
75 const char *key)
76 {
77 size_t key_len;
78 struct zcbor_map_decode_key_val *dptr = map;
79
80 /* Lazy run, comparing pointers only assuming that compiler will be able to store
81 * read-only string of the same value as single instance.
82 */
83 while (dptr < (map + map_size)) {
84 if (dptr->key.value == (const uint8_t *)key) {
85 return dptr->found;
86 }
87 ++dptr;
88 }
89
90 /* Lazy run failed so need to do real comprison */
91 key_len = strlen(key);
92 dptr = map;
93
94 while (dptr < (map + map_size)) {
95 if (dptr->key.len == key_len &&
96 memcmp(key, dptr->key.value, key_len) == 0) {
97 return dptr->found;
98 }
99 ++dptr;
100 }
101
102 return false;
103 }
104
zcbor_map_decode_bulk_reset(struct zcbor_map_decode_key_val * map,size_t map_size)105 void zcbor_map_decode_bulk_reset(struct zcbor_map_decode_key_val *map, size_t map_size)
106 {
107 for (size_t map_index = 0; map_index < map_size; ++map_index) {
108 map[map_index].found = false;
109 }
110 }
111