1 /*
2  * Copyright (c) 2020 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 /**@file nrf_802154_kvmap.h
36  * @brief Simple key-value map.
37  */
38 
39 #ifndef NRF_802154_KVMAP_H_INCLUDED__
40 #define NRF_802154_KVMAP_H_INCLUDED__
41 
42 #include <stdbool.h>
43 #include <stddef.h>
44 
45 /**@brief Structure representing a key-value map */
46 typedef struct
47 {
48     /**@brief Pointer to a memory used to store items */
49     void * p_memory;
50     /**@brief Maximum number of items the key-value map instance is able to store */
51     size_t capacity;
52     /**@brief Number of currently stored items */
53     size_t count;
54     /**@brief Size of a key in bytes */
55     size_t key_size;
56     /**@brief Size of a value in bytes */
57     size_t val_size;
58 } nrf_802154_kvmap_t;
59 
60 /**@brief Calculates capacity of memory required to store a key-value map.
61  *
62  * Example:
63  * @code
64  * static uint8_t m_map_memory[NRF_802154_KVMAP_MEMORY_SIZE(10, 7, 6)];
65  * static nrf_802154_kvmap_t m_map;
66  *
67  * nrf_802154_kvmap_init(&m_map, m_map_memory, sizeof(m_map_memory),
68  *                       7, 6);
69  * @endcode
70  */
71 #define NRF_802154_KVMAP_MEMORY_SIZE(capacity, key_size, val_size) \
72     ((capacity) * ((key_size) + (val_size)))
73 
74 /**@brief Initializes a key-value map instance.
75  *
76  * @param[out] p_kvmap  Pointer to an object to initialize.
77  *                      The pointed object should persist as long as the map is in use.
78  *                      Cannot be NULL.
79  * @param[in] p_memory  Pointer to a memory to be used as items storage.
80  *                      Memory pointed by this pointer should persist as long as
81  *                      the map pointed by @p p_kvmap is in use.
82  *                      Cannot be NULL (with exception, when memsize is 0)
83  * @param[in] memsize   Size of the memory pointed by @p p_memory. When defining
84  *                      storage you can use @ref NRF_802154_KVMAP_MEMORY_SIZE helper macro.
85  * @param[in] key_size  Size of the key in bytes within the map. This must be greater than 0.
86  *                      Please note that keys are compared by @ref memcmp. If a key is a
87  *                      struct beware of padding in key structs.
88  * @param[in] val_size  Size of the value in bytes within the map. This can be 0 if the map
89  *                      is used to store keys only.
90  */
91 void nrf_802154_kvmap_init(nrf_802154_kvmap_t * p_kvmap,
92                            void               * p_memory,
93                            size_t               memsize,
94                            size_t               key_size,
95                            size_t               val_size);
96 
97 /**@brief Returns total number of items a key-value map can store
98  *
99  * @param[in] p_kvmap   Pointer to a key-value map to examine
100  *
101  * @return              Number of items a key-value map can store
102  */
nrf_802154_kvmap_capacity(const nrf_802154_kvmap_t * p_kvmap)103 static inline size_t nrf_802154_kvmap_capacity(const nrf_802154_kvmap_t * p_kvmap)
104 {
105     return p_kvmap->capacity;
106 }
107 
108 /**@brief Returns current number of items a key-value actually holds.
109  *
110  * @param[in] p_kvmap   Pointer to a key-value map to examine
111  *
112  * @return              Number of items a key-value map can store
113  */
nrf_802154_kvmap_count(const nrf_802154_kvmap_t * p_kvmap)114 static inline size_t nrf_802154_kvmap_count(const nrf_802154_kvmap_t * p_kvmap)
115 {
116     return p_kvmap->count;
117 }
118 
119 /**@brief Adds a key-value pair to a map.
120  *
121  * @param[in,out] p_kvmap   Pointer to a key-value map to modify
122  * @param[in]     p_key     Pointer to a key to add. Must not be NULL. The size must
123  *                          correspond to @c key_size passed to recent
124  *                          @ref nrf_802154_kvmap_init
125  * @param[in]     p_value   Pointer to a value associated with the key to add. The size must
126  *                          correspond to @c val_size passed to recent
127  *                          @ref nrf_802154_kvmap_init. This pointer can be NULL when
128  *                          the @val_size used to initialize was 0.
129  *
130  * @retval true     The key-value pair was successfully added to the map.
131  *                  This value is returned also when the key was already present in
132  *                  the map. In this case just the value is updated.
133  * @retval false    Maximum capacity of the map has been reached and new item
134  *                  could not be added.
135  */
136 bool nrf_802154_kvmap_add(nrf_802154_kvmap_t * p_kvmap,
137                           const void         * p_key,
138                           const void         * p_value);
139 
140 /**@brief Removes a key-value pair from a map.
141  *
142  * @param[in,out] p_kvmap   Pointer to a key-value map to modify
143  * @param[in]     p_key     Pointer to a key to remove. Must not be NULL.
144  *                          The size of a memory pointed by @p p_key must correspond to
145  *                          @c key_size passed to recent call to @ref nrf_802154_kvmap_init.
146  *
147  * @retval true     The key was present in the map and has been removed.
148  * @retval false    The key was not found in the map. The map in unmodified.
149  */
150 bool nrf_802154_kvmap_remove(nrf_802154_kvmap_t * p_kvmap, const void * p_key);
151 
152 /**@brief Searches for a key in a key-value map.
153  *
154  * @param[in]  p_kvmap  Pointer to a key-value map to search.
155  * @param[in]  p_key    Pointer to a key to search. Must not be NULL.
156  *                      The size of a memory pointed by @p p_key must correspond to
157  *                      @c key_size passed to recent call @ref nrf_802154_kvmap_init.
158  * @param[out] p_value  If NULL. No value associated with potentially found key is retrieved.
159  *                      If not NULL the size of a memory pointed by @p p_value must
160  *                      correspond to @c val_size passed to recent @ref nrf_802154_kvmap_init.
161  *                      When the key is found, the value associated with the key is stored
162  *                      behind @p p_value. When the key is not found memory behind this
163  *                      pointer remains unmodified.
164  *
165  * @retval true     The key has been found. Value associated with the key is available
166  *                  behind @p p_value pointer if @p p_value passed was not NULL.
167  * @retval false    The key has not been found. Memory pointed by @p p_value
168  *                  has been not modified.
169  */
170 bool nrf_802154_kvmap_search(const nrf_802154_kvmap_t * p_kvmap,
171                              const void               * p_key,
172                              void                     * p_value);
173 
174 #endif /* NRF_802154_KVMAP_H_INCLUDED__ */
175