Skip to content

Commit b98ac15

Browse files
nburekjacobperron
authored andcommitted
Adding an ArrayList and HashMap implementation to rcutils (#131)
* Adding an ArrayList and HashMap data structures along with tests. * Fixup for PR. * Fix typo. Co-Authored-By: nburek <NickBurek@gmail.com> * Fix typo. Co-Authored-By: nburek <NickBurek@gmail.com> * Fixing typo. Co-Authored-By: nburek <NickBurek@gmail.com> * Minor fixup for PR.
1 parent 3630b90 commit b98ac15

File tree

8 files changed

+2283
-0
lines changed

8 files changed

+2283
-0
lines changed

CMakeLists.txt

+16
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ endif()
3030

3131
set(rcutils_sources
3232
src/allocator.c
33+
src/array_list.c
3334
src/char_array.c
3435
src/cmdline_parser.c
3536
src/error_handling.c
3637
src/filesystem.c
3738
src/find.c
3839
src/format_string.c
3940
src/get_env.c
41+
src/hash_map.c
4042
src/logging.c
4143
src/repl_str.c
4244
src/snprintf.c
@@ -312,6 +314,20 @@ if(BUILD_TESTING)
312314
if(TARGET test_uint8_array)
313315
target_link_libraries(test_uint8_array ${PROJECT_NAME})
314316
endif()
317+
318+
rcutils_custom_add_gtest(test_array_list
319+
test/test_array_list.cpp
320+
)
321+
if(TARGET test_array_list)
322+
target_link_libraries(test_array_list ${PROJECT_NAME})
323+
endif()
324+
325+
rcutils_custom_add_gtest(test_hash_map
326+
test/test_hash_map.cpp
327+
)
328+
if(TARGET test_hash_map)
329+
target_link_libraries(test_hash_map ${PROJECT_NAME})
330+
endif()
315331
endif()
316332

317333
ament_export_dependencies(ament_cmake)

include/rcutils/types/array_list.h

+284
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
// Copyright 2018-2019 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCUTILS__TYPES__ARRAY_LIST_H_
16+
#define RCUTILS__TYPES__ARRAY_LIST_H_
17+
18+
#ifdef __cplusplus
19+
extern "C"
20+
{
21+
#endif
22+
23+
#include <string.h>
24+
25+
#include "rcutils/allocator.h"
26+
#include "rcutils/macros.h"
27+
#include "rcutils/types/rcutils_ret.h"
28+
#include "rcutils/visibility_control.h"
29+
30+
struct rcutils_array_list_impl_t;
31+
32+
typedef struct RCUTILS_PUBLIC_TYPE rcutils_array_list_t
33+
{
34+
struct rcutils_array_list_impl_t * impl;
35+
} rcutils_array_list_t;
36+
37+
/**
38+
* Validates that an rcutils_array_list_t* points to a valid array list.
39+
* \param array_list A pointer to an rcutils_array_list_t
40+
* \return RCUTILS_RET_INVALID_ARGUMENT if array_list is null
41+
* \return RCUTILS_RET_NOT_INITIALIZED if array_list is not initialized
42+
*/
43+
#define ARRAY_LIST_VALIDATE_ARRAY_LIST(array_list) \
44+
RCUTILS_CHECK_ARGUMENT_FOR_NULL(array_list, RCUTILS_RET_INVALID_ARGUMENT); \
45+
if (NULL == array_list->impl) { \
46+
RCUTILS_SET_ERROR_MSG("array_list is not initialized"); \
47+
return RCUTILS_RET_NOT_INITIALIZED; \
48+
}
49+
50+
/// Return an empty array_list struct.
51+
/**
52+
* This function returns an empty and zero initialized array_list struct.
53+
* Calling rcutils_array_list_fini() on any non-initialized instance leads
54+
* to undefined behavior.
55+
* Every instance of array_list_t has to either be zero_initialized with this
56+
* function or manually allocated.
57+
*
58+
* <hr>
59+
* Attribute | Adherence
60+
* ------------------ | -------------
61+
* Allocates Memory | No
62+
* Thread-Safe | Yes
63+
* Uses Atomics | No
64+
* Lock-Free | Yes
65+
*
66+
* Example:
67+
*
68+
* ```c
69+
* rcutils_array_list_t foo;
70+
* rcutils_array_list_fini(&foo); // undefined behavior!
71+
*
72+
* rcutils_array_list_t bar = rcutils_get_zero_initialized_array_list();
73+
* rcutils_array_list_fini(&bar); // ok
74+
* ```
75+
*/
76+
RCUTILS_PUBLIC
77+
rcutils_array_list_t
78+
rcutils_get_zero_initialized_array_list(void);
79+
80+
/// Initialize an array list with a given initial capacity.
81+
/**
82+
* This function will initialize a given, zero initialized, array_list to
83+
* a given size.
84+
*
85+
* <hr>
86+
* Attribute | Adherence
87+
* ------------------ | -------------
88+
* Allocates Memory | Yes
89+
* Thread-Safe | No
90+
* Uses Atomics | No
91+
* Lock-Free | Yes
92+
*
93+
* Example:
94+
*
95+
* ```c
96+
* rcutils_allocator_t allocator = rcutils_get_default_allocator();
97+
* rcutils_array_list_t array_list = rcutils_get_zero_initialized_array_list();
98+
* rcutils_ret_t ret = rcutils_array_list_init(&array_list, 2, sizeof(int), &allocator);
99+
* if (ret != RCUTILS_RET_OK) {
100+
* // ... error handling
101+
* }
102+
* int data = 42;
103+
* int out_data = 0;
104+
* ret = rcutils_array_list_add(&array_list, &data);
105+
* data++;
106+
* ret = rcutils_array_list_get(&array_list, 0, &out_data);
107+
* assert(42 == out_data);
108+
* ret = rcutils_array_list_fini(&array_list);
109+
* ```
110+
*
111+
* \param[inout] array_list object to be initialized
112+
* \param[in] initial_capacity the initial capacity to allocate in the list
113+
* \param[in] data_size the size (in bytes) of the data object being stored in the list
114+
* \param[in] allocator to be used to allocate and deallocate memory
115+
* \return `RCUTILS_RET_OK` if successful, or
116+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
117+
* \return `RCUTILS_RET_BAD_ALLOC` if memory allocation fails, or
118+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
119+
*/
120+
RCUTILS_PUBLIC
121+
rcutils_ret_t
122+
rcutils_array_list_init(
123+
rcutils_array_list_t * array_list,
124+
size_t initial_capacity,
125+
size_t data_size,
126+
const rcutils_allocator_t * allocator);
127+
128+
/// Finalize an array list, reclaiming all resources.
129+
/**
130+
* This function reclaims any memory owned by the array list.
131+
*
132+
* The allocator used to initialize the array list is used to deallocate each
133+
* entry in the list and the list itself.
134+
*
135+
* <hr>
136+
* Attribute | Adherence
137+
* ------------------ | -------------
138+
* Allocates Memory | No
139+
* Thread-Safe | No
140+
* Uses Atomics | No
141+
* Lock-Free | Yes
142+
*
143+
* \param[inout] array_list object to be finalized
144+
* \return `RCUTILS_RET_OK` if successful, or
145+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
146+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
147+
*/
148+
RCUTILS_PUBLIC
149+
RCUTILS_WARN_UNUSED
150+
rcutils_ret_t
151+
rcutils_array_list_fini(rcutils_array_list_t * array_list);
152+
153+
/// Adds an entry to the list
154+
/**
155+
* This function adds the provided data to the end of the list. A shallow copy of
156+
* the provided data is made to store in the list instead of just storing
157+
* the pointer to the provided data.
158+
*
159+
* <hr>
160+
* Attribute | Adherence
161+
* ------------------ | -------------
162+
* Allocates Memory | Yes
163+
* Thread-Safe | No
164+
* Uses Atomics | No
165+
* Lock-Free | Yes
166+
*
167+
* \param[in] array_list to add the data to
168+
* \param[in] data a pointer to the data to add to the list
169+
* \return `RCUTILS_RET_OK` if successful, or
170+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
171+
* \return `RCUTILS_RET_BAD_ALLOC` if memory allocation fails, or
172+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
173+
*/
174+
RCUTILS_PUBLIC
175+
RCUTILS_WARN_UNUSED
176+
rcutils_ret_t
177+
rcutils_array_list_add(rcutils_array_list_t * array_list, const void * data);
178+
179+
/// Sets an entry in the list to the provided data
180+
/**
181+
* This function sets the provided data at the specified index in the list.
182+
* A shallow copy of the provided data is made to store in the list instead
183+
* of just storing the pointer to the provided data.
184+
*
185+
* <hr>
186+
* Attribute | Adherence
187+
* ------------------ | -------------
188+
* Allocates Memory | No
189+
* Thread-Safe | No
190+
* Uses Atomics | No
191+
* Lock-Free | Yes
192+
*
193+
* \param[in] array_list to add the data to
194+
* \param[in] index the position in the list to set the data
195+
* \param[in] data a pointer to the data that will be set in the list
196+
* \return `RCUTILS_RET_OK` if successful, or
197+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
198+
* \return `RCUTILS_RET_INVALID_ARGUMENT` if index out of bounds, or
199+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
200+
*/
201+
RCUTILS_PUBLIC
202+
RCUTILS_WARN_UNUSED
203+
rcutils_ret_t
204+
rcutils_array_list_set(rcutils_array_list_t * array_list, size_t index, const void * data);
205+
206+
/// Removes an entry in the list at the provided index
207+
/**
208+
* This function removes data from the list at the specified index. The capacity
209+
* of the list will never decrease when entries are removed.
210+
*
211+
* <hr>
212+
* Attribute | Adherence
213+
* ------------------ | -------------
214+
* Allocates Memory | No
215+
* Thread-Safe | No
216+
* Uses Atomics | No
217+
* Lock-Free | Yes
218+
*
219+
* \param[in] array_list to add the data to
220+
* \param[in] index the index of the item to remove from the list
221+
* \return `RCUTILS_RET_OK` if successful, or
222+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
223+
* \return `RCUTILS_RET_INVALID_ARGUMENT` if index out of bounds, or
224+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
225+
*/
226+
RCUTILS_PUBLIC
227+
RCUTILS_WARN_UNUSED
228+
rcutils_ret_t
229+
rcutils_array_list_remove(rcutils_array_list_t * array_list, size_t index);
230+
231+
/// Retrieves an entry in the list at the provided index
232+
/**
233+
* This function retrieves a copy of the data stored in the list at the provided index.
234+
*
235+
* <hr>
236+
* Attribute | Adherence
237+
* ------------------ | -------------
238+
* Allocates Memory | No
239+
* Thread-Safe | No
240+
* Uses Atomics | No
241+
* Lock-Free | Yes
242+
*
243+
*
244+
* \param[in] array_list to add the data to
245+
* \param[in] index the index at which to get the data
246+
* \param[out] data a copy of the data stored in the list
247+
* \return `RCUTILS_RET_OK` if successful, or
248+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
249+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
250+
*/
251+
RCUTILS_PUBLIC
252+
RCUTILS_WARN_UNUSED
253+
rcutils_ret_t
254+
rcutils_array_list_get(const rcutils_array_list_t * array_list, size_t index, void * data);
255+
256+
/// Retrieves the size of the provided array_list
257+
/**
258+
* This function retrieves the number of items in the provided array list
259+
*
260+
* <hr>
261+
* Attribute | Adherence
262+
* ------------------ | -------------
263+
* Allocates Memory | No
264+
* Thread-Safe | No
265+
* Uses Atomics | No
266+
* Lock-Free | Yes
267+
*
268+
*
269+
* \param[in] array_list list to get the size of
270+
* \param[out] size The number of items currently stored in the list
271+
* \return `RCUTILS_RET_OK` if successful, or
272+
* \return `RCUTILS_RET_INVALID_ARGUMENT` for invalid arguments, or
273+
* \return `RCUTILS_RET_ERROR` if an unknown error occurs
274+
*/
275+
RCUTILS_PUBLIC
276+
RCUTILS_WARN_UNUSED
277+
rcutils_ret_t
278+
rcutils_array_list_get_size(const rcutils_array_list_t * array_list, size_t * size);
279+
280+
#ifdef __cplusplus
281+
}
282+
#endif
283+
284+
#endif // RCUTILS__TYPES__ARRAY_LIST_H_

0 commit comments

Comments
 (0)