@@ -29,10 +29,15 @@ extern "C"
2929#include "rcutils/format_string.h"
3030#include "rcutils/types/rcutils_ret.h"
3131
32+ typedef struct key_value_pair
33+ {
34+ char * key ;
35+ char * value ;
36+ } key_value_pair_t ;
37+
3238typedef struct rcutils_string_map_impl_s
3339{
34- char * * keys ;
35- char * * values ;
40+ key_value_pair_t * key_value_pairs ;
3641 size_t capacity ;
3742 size_t size ;
3843 rcutils_allocator_t allocator ;
@@ -64,8 +69,7 @@ rcutils_string_map_init(
6469 RCUTILS_SET_ERROR_MSG ("failed to allocate memory for string map impl struct" );
6570 return RCUTILS_RET_BAD_ALLOC ;
6671 }
67- string_map -> impl -> keys = NULL ;
68- string_map -> impl -> values = NULL ;
72+ string_map -> impl -> key_value_pairs = NULL ;
6973 string_map -> impl -> capacity = 0 ;
7074 string_map -> impl -> size = 0 ;
7175 string_map -> impl -> allocator = allocator ;
@@ -130,6 +134,17 @@ rcutils_string_map_get_size(const rcutils_string_map_t * string_map, size_t * si
130134 return RCUTILS_RET_OK ;
131135}
132136
137+ static void
138+ __remove_key_and_value_at_index (rcutils_string_map_impl_t * string_map_impl , size_t index )
139+ {
140+ rcutils_allocator_t allocator = string_map_impl -> allocator ;
141+ allocator .deallocate (string_map_impl -> key_value_pairs [index ].key , allocator .state );
142+ string_map_impl -> key_value_pairs [index ].key = NULL ;
143+ allocator .deallocate (string_map_impl -> key_value_pairs [index ].value , allocator .state );
144+ string_map_impl -> key_value_pairs [index ].value = NULL ;
145+ string_map_impl -> size -- ;
146+ }
147+
133148rcutils_ret_t
134149rcutils_string_map_reserve (rcutils_string_map_t * string_map , size_t capacity )
135150{
@@ -147,46 +162,35 @@ rcutils_string_map_reserve(rcutils_string_map_t * string_map, size_t capacity)
147162 return RCUTILS_RET_OK ;
148163 } else if (capacity == 0 ) {
149164 // if the requested capacity is zero, then make sure the existing keys and values are free'd
150- allocator .deallocate (string_map -> impl -> keys , allocator .state );
151- string_map -> impl -> keys = NULL ;
152- allocator .deallocate (string_map -> impl -> values , allocator .state );
153- string_map -> impl -> values = NULL ;
165+ // size is known to be 0 here because of the recursive call above.
166+ allocator .deallocate (string_map -> impl -> key_value_pairs , allocator .state );
167+ string_map -> impl -> key_value_pairs = NULL ;
154168 // falls through to normal function end
155169 } else {
156170 // if the capacity non-zero and different, use realloc to increase/shrink the size
157171 // note that realloc when the pointer is NULL is the same as malloc
158172 // note also that realloc will shrink the space if needed
159173
160- // ensure that reallocate won't overflow capacity
161- if (capacity > (SIZE_MAX / sizeof (char * ))) {
174+ // ensure that reallocate won't overflow SIZE_MAX
175+ if (capacity > (SIZE_MAX / sizeof (key_value_pair_t ))) {
162176 RCUTILS_SET_ERROR_MSG ("requested capacity for string_map too large" );
163177 return RCUTILS_RET_BAD_ALLOC ;
164178 }
165179
166- // resize the keys, assigning the result only if it succeeds
167- char * * new_keys =
168- allocator .reallocate (string_map -> impl -> keys , capacity * sizeof (char * ), allocator .state );
169- if (NULL == new_keys ) {
170- RCUTILS_SET_ERROR_MSG ("failed to allocate memory for string_map keys" );
171- return RCUTILS_RET_BAD_ALLOC ;
172- }
173- string_map -> impl -> keys = new_keys ;
174-
175- // resize the values, assigning the result only if it succeeds
176- char * * new_values =
177- allocator .reallocate (string_map -> impl -> values , capacity * sizeof (char * ), allocator .state );
178- if (NULL == new_values ) {
179- RCUTILS_SET_ERROR_MSG ("failed to allocate memory for string_map values" );
180+ // resize the keys and values, assigning the result only if it succeeds
181+ key_value_pair_t * new_key_value_pairs = allocator .reallocate (
182+ string_map -> impl -> key_value_pairs , capacity * sizeof (key_value_pair_t ), allocator .state );
183+ if (NULL == new_key_value_pairs ) {
184+ RCUTILS_SET_ERROR_MSG ("failed to allocate memory for string_map key-value pairs" );
180185 return RCUTILS_RET_BAD_ALLOC ;
181186 }
182- string_map -> impl -> values = new_values ;
187+ string_map -> impl -> key_value_pairs = new_key_value_pairs ;
183188
184189 // zero out the new memory, if there is any (expanded instead of shrunk)
185190 if (capacity > string_map -> impl -> capacity ) {
186- size_t i = string_map -> impl -> capacity ;
187- for (; i < capacity ; ++ i ) {
188- string_map -> impl -> keys [i ] = NULL ;
189- string_map -> impl -> values [i ] = NULL ;
191+ for (size_t i = string_map -> impl -> capacity ; i < capacity ; ++ i ) {
192+ string_map -> impl -> key_value_pairs [i ].key = NULL ;
193+ string_map -> impl -> key_value_pairs [i ].value = NULL ;
190194 }
191195 }
192196 // falls through to normal function end
@@ -195,29 +199,19 @@ rcutils_string_map_reserve(rcutils_string_map_t * string_map, size_t capacity)
195199 return RCUTILS_RET_OK ;
196200}
197201
198- static void
199- __remove_key_and_value_at_index (rcutils_string_map_impl_t * string_map_impl , size_t index )
200- {
201- rcutils_allocator_t allocator = string_map_impl -> allocator ;
202- allocator .deallocate (string_map_impl -> keys [index ], allocator .state );
203- string_map_impl -> keys [index ] = NULL ;
204- allocator .deallocate (string_map_impl -> values [index ], allocator .state );
205- string_map_impl -> values [index ] = NULL ;
206- string_map_impl -> size -- ;
207- }
208-
209202rcutils_ret_t
210203rcutils_string_map_clear (rcutils_string_map_t * string_map )
211204{
212205 RCUTILS_CHECK_ARGUMENT_FOR_NULL (string_map , RCUTILS_RET_INVALID_ARGUMENT );
213206 RCUTILS_CHECK_FOR_NULL_WITH_MSG (
214207 string_map -> impl , "invalid string map" , return RCUTILS_RET_STRING_MAP_INVALID );
215- size_t i = 0 ;
216- for (; i < string_map -> impl -> capacity ; ++ i ) {
217- if (string_map -> impl -> keys [i ] != NULL ) {
208+
209+ for (size_t i = 0 ; i < string_map -> impl -> capacity ; ++ i ) {
210+ if (string_map -> impl -> key_value_pairs [i ]. key != NULL ) {
218211 __remove_key_and_value_at_index (string_map -> impl , i );
219212 }
220213 }
214+
221215 return RCUTILS_RET_OK ;
222216}
223217
@@ -255,14 +249,14 @@ __get_index_of_key_if_exists(
255249{
256250 size_t i = 0 ;
257251 for (; i < string_map_impl -> capacity ; ++ i ) {
258- if (NULL == string_map_impl -> keys [i ]) {
252+ if (NULL == string_map_impl -> key_value_pairs [i ]. key ) {
259253 continue ;
260254 }
261- size_t cmp_count = strlen (string_map_impl -> keys [i ]);
255+ size_t cmp_count = strlen (string_map_impl -> key_value_pairs [i ]. key );
262256 if (key_length > cmp_count ) {
263257 cmp_count = key_length ;
264258 }
265- if (strncmp (key , string_map_impl -> keys [i ], cmp_count ) == 0 ) {
259+ if (strncmp (key , string_map_impl -> key_value_pairs [i ]. key , cmp_count ) == 0 ) {
266260 * index = i ;
267261 return true;
268262 }
@@ -292,30 +286,30 @@ rcutils_string_map_set_no_resize(
292286 return RCUTILS_RET_NOT_ENOUGH_SPACE ;
293287 }
294288 for (key_index = 0 ; key_index < string_map -> impl -> capacity ; ++ key_index ) {
295- if (NULL == string_map -> impl -> keys [key_index ]) {
289+ if (NULL == string_map -> impl -> key_value_pairs [key_index ]. key ) {
296290 break ;
297291 }
298292 }
299293 assert (key_index < string_map -> impl -> capacity ); // defensive, this should not happen
300- string_map -> impl -> keys [key_index ] = rcutils_strdup (key , allocator );
301- if (NULL == string_map -> impl -> keys [key_index ]) {
294+ string_map -> impl -> key_value_pairs [key_index ]. key = rcutils_strdup (key , allocator );
295+ if (NULL == string_map -> impl -> key_value_pairs [key_index ]. key ) {
302296 RCUTILS_SET_ERROR_MSG ("failed to allocate memory for key" );
303297 return RCUTILS_RET_BAD_ALLOC ;
304298 }
305299 should_free_key_on_error = true;
306300 }
307301 // at this point the key is in the map, waiting for the value to set/overwritten
308- char * original_value = string_map -> impl -> values [key_index ];
302+ char * original_value = string_map -> impl -> key_value_pairs [key_index ]. value ;
309303 char * new_value = rcutils_strdup (value , allocator );
310304 if (NULL == new_value ) {
311- RCUTILS_SET_ERROR_MSG ("failed to allocate memory for key " );
305+ RCUTILS_SET_ERROR_MSG ("failed to allocate memory for value " );
312306 if (should_free_key_on_error ) {
313- allocator .deallocate (string_map -> impl -> keys [key_index ], allocator .state );
314- string_map -> impl -> keys [key_index ] = NULL ;
307+ allocator .deallocate (string_map -> impl -> key_value_pairs [key_index ]. key , allocator .state );
308+ string_map -> impl -> key_value_pairs [key_index ]. key = NULL ;
315309 }
316310 return RCUTILS_RET_BAD_ALLOC ;
317311 }
318- string_map -> impl -> values [key_index ] = new_value ;
312+ string_map -> impl -> key_value_pairs [key_index ]. value = new_value ;
319313 if (original_value != NULL ) {
320314 // clean up the old value if not NULL
321315 allocator .deallocate (original_value , allocator .state );
@@ -386,7 +380,7 @@ rcutils_string_map_getn(
386380 }
387381 size_t key_index ;
388382 if (__get_index_of_key_if_exists (string_map -> impl , key , key_length , & key_index )) {
389- return string_map -> impl -> values [key_index ];
383+ return string_map -> impl -> key_value_pairs [key_index ]. value ;
390384 }
391385 return NULL ;
392386}
@@ -408,7 +402,7 @@ rcutils_string_map_get_next_key(
408402 bool given_key_found = false;
409403 size_t i = 0 ;
410404 for (; i < string_map -> impl -> capacity ; ++ i ) {
411- if (string_map -> impl -> keys [i ] == key ) {
405+ if (string_map -> impl -> key_value_pairs [i ]. key == key ) {
412406 given_key_found = true;
413407 // given key found at index i, start there + 1
414408 start_index = i + 1 ;
@@ -422,9 +416,9 @@ rcutils_string_map_get_next_key(
422416 // iterate through the storage and look for another non-NULL key to return
423417 size_t i = start_index ;
424418 for (; i < string_map -> impl -> capacity ; ++ i ) {
425- if (string_map -> impl -> keys [i ] != NULL ) {
419+ if (string_map -> impl -> key_value_pairs [i ]. key != NULL ) {
426420 // next key found, return it
427- return string_map -> impl -> keys [i ];
421+ return string_map -> impl -> key_value_pairs [i ]. key ;
428422 }
429423 }
430424 // next key (or first key) not found
0 commit comments