1 /*
2 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2006 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * $COPYRIGHT$
13 *
14 * Additional copyrights may follow
15 *
16 * $HEADER$
17 */
18
19 #ifndef OPAL_VALUE_ARRAY_H
20 #define OPAL_VALUE_ARRAY_H
21
22 #include "opal_config.h"
23
24 #include <string.h>
25 #ifdef HAVE_STRINGS_H
26 #include <strings.h>
27 #endif /* HAVE_STRINGS_H */
28
29 #include "opal/class/opal_object.h"
30 #if OPAL_ENABLE_DEBUG
31 #include "opal/util/output.h"
32 #endif
33 #include "opal/constants.h"
34
35 BEGIN_C_DECLS
36
37 /*
38 * @file Array of elements maintained by value.
39 */
40
41 struct opal_value_array_t
42 {
43 opal_object_t super;
44 unsigned char* array_items;
45 size_t array_item_sizeof;
46 size_t array_size;
47 size_t array_alloc_size;
48 };
49 typedef struct opal_value_array_t opal_value_array_t;
50
51 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_value_array_t);
52
53 /**
54 * Initialize the array to hold items by value. This routine must
55 * be called prior to using the array.
56 *
57 * @param array The array to initialize (IN).
58 * @param item_size The sizeof each array element (IN).
59 * @return OPAL error code
60 *
61 * Note that there is no corresponding "finalize" function -- use
62 * OBJ_DESTRUCT (for stack arrays) or OBJ_RELEASE (for heap arrays) to
63 * delete it.
64 */
65
opal_value_array_init(opal_value_array_t * array,size_t item_sizeof)66 static inline int opal_value_array_init(opal_value_array_t *array, size_t item_sizeof)
67 {
68 array->array_item_sizeof = item_sizeof;
69 array->array_alloc_size = 1;
70 array->array_size = 0;
71 array->array_items = (unsigned char*)realloc(array->array_items, item_sizeof * array->array_alloc_size);
72 return (NULL != array->array_items) ? OPAL_SUCCESS : OPAL_ERR_OUT_OF_RESOURCE;
73 }
74
75
76 /**
77 * Reserve space in the array for new elements, but do not change the size.
78 *
79 * @param array The input array (IN).
80 * @param size The anticipated size of the array (IN).
81 * @return OPAL error code.
82 */
83
opal_value_array_reserve(opal_value_array_t * array,size_t size)84 static inline int opal_value_array_reserve(opal_value_array_t* array, size_t size)
85 {
86 if(size > array->array_alloc_size) {
87 array->array_items = (unsigned char*)realloc(array->array_items, array->array_item_sizeof * size);
88 if(NULL == array->array_items) {
89 array->array_size = 0;
90 array->array_alloc_size = 0;
91 return OPAL_ERR_OUT_OF_RESOURCE;
92 }
93 array->array_alloc_size = size;
94 }
95 return OPAL_SUCCESS;
96 }
97
98
99
100 /**
101 * Retreives the number of elements in the array.
102 *
103 * @param array The input array (IN).
104 * @return The number of elements currently in use.
105 */
106
opal_value_array_get_size(opal_value_array_t * array)107 static inline size_t opal_value_array_get_size(opal_value_array_t* array)
108 {
109 return array->array_size;
110 }
111
112
113 /**
114 * Set the number of elements in the array.
115 *
116 * @param array The input array (IN).
117 * @param size The new array size.
118 *
119 * @return OPAL error code.
120 *
121 * Note that resizing the array to a smaller size may not change
122 * the underlying memory allocated by the array. However, setting
123 * the size larger than the current allocation will grow it. In either
124 * case, if the routine is successful, opal_value_array_get_size() will
125 * return the new size.
126 */
127
128 OPAL_DECLSPEC int opal_value_array_set_size(opal_value_array_t* array, size_t size);
129
130
131 /**
132 * Macro to retrieve an item from the array by value.
133 *
134 * @param array The input array (IN).
135 * @param item_type The C datatype of the array item (IN).
136 * @param item_index The array index (IN).
137 *
138 * @returns item The requested item.
139 *
140 * Note that this does not change the size of the array - this macro is
141 * strictly for performance - the user assumes the responsibility of
142 * ensuring the array index is valid (0 <= item index < array size).
143 */
144
145 #define OPAL_VALUE_ARRAY_GET_ITEM(array, item_type, item_index) \
146 ((item_type*)((array)->array_items))[item_index]
147
148 /**
149 * Retrieve an item from the array by reference.
150 *
151 * @param array The input array (IN).
152 * @param item_index The array index (IN).
153 *
154 * @return ptr Pointer to the requested item.
155 *
156 * Note that if the specified item_index is larger than the current
157 * array size, the array is grown to satisfy the request.
158 */
159
opal_value_array_get_item(opal_value_array_t * array,size_t item_index)160 static inline void* opal_value_array_get_item(opal_value_array_t *array, size_t item_index)
161 {
162 if(item_index >= array->array_size && opal_value_array_set_size(array, item_index+1) != OPAL_SUCCESS)
163 return NULL;
164 return array->array_items + (item_index * array->array_item_sizeof);
165 }
166
167 /**
168 * Macro to set an array element by value.
169 *
170 * @param array The input array (IN).
171 * @param item_type The C datatype of the array item (IN).
172 * @param item_index The array index (IN).
173 * @param item_value The new value for the specified index (IN).
174 *
175 * Note that this does not change the size of the array - this macro is
176 * strictly for performance - the user assumes the responsibility of
177 * ensuring the array index is valid (0 <= item index < array size).
178 *
179 * It is safe to free the item after returning from this call; it is
180 * copied into the array by value.
181 */
182
183 #define OPAL_VALUE_ARRAY_SET_ITEM(array, item_type, item_index, item_value) \
184 (((item_type*)((array)->array_items))[item_index] = item_value)
185
186 /**
187 * Set an array element by value.
188 *
189 * @param array The input array (IN).
190 * @param item_index The array index (IN).
191 * @param item_value A pointer to the item, which is copied into
192 * the array.
193 *
194 * @return OPAL error code.
195 *
196 * It is safe to free the item after returning from this call; it is
197 * copied into the array by value.
198 */
199
opal_value_array_set_item(opal_value_array_t * array,size_t item_index,const void * item)200 static inline int opal_value_array_set_item(opal_value_array_t *array, size_t item_index, const void* item)
201 {
202 int rc;
203 if(item_index >= array->array_size &&
204 (rc = opal_value_array_set_size(array, item_index+1)) != OPAL_SUCCESS)
205 return rc;
206 memcpy(array->array_items + (item_index * array->array_item_sizeof), item, array->array_item_sizeof);
207 return OPAL_SUCCESS;
208 }
209
210
211 /**
212 * Appends an item to the end of the array.
213 *
214 * @param array The input array (IN).
215 * @param item A pointer to the item to append, which is copied
216 * into the array.
217 *
218 * @return OPAL error code
219 *
220 * This will grow the array if it is not large enough to contain the
221 * item. It is safe to free the item after returning from this call;
222 * it is copied by value into the array.
223 */
224
opal_value_array_append_item(opal_value_array_t * array,const void * item)225 static inline int opal_value_array_append_item(opal_value_array_t *array, const void *item)
226 {
227 return opal_value_array_set_item(array, array->array_size, item);
228 }
229
230
231 /**
232 * Remove a specific item from the array.
233 *
234 * @param array The input array (IN).
235 * @param item_index The index to remove, which must be less than
236 * the current array size (IN).
237 *
238 * @return OPAL error code.
239 *
240 * All elements following this index are shifted down.
241 */
242
opal_value_array_remove_item(opal_value_array_t * array,size_t item_index)243 static inline int opal_value_array_remove_item(opal_value_array_t *array, size_t item_index)
244 {
245 #if OPAL_ENABLE_DEBUG
246 if (item_index >= array->array_size) {
247 opal_output(0, "opal_value_array_remove_item: invalid index %lu\n", (unsigned long)item_index);
248 return OPAL_ERR_BAD_PARAM;
249 }
250 #endif
251 memmove(array->array_items+(array->array_item_sizeof * item_index),
252 array->array_items+(array->array_item_sizeof * (item_index+1)),
253 array->array_item_sizeof * (array->array_size - item_index - 1));
254 array->array_size--;
255 return OPAL_SUCCESS;
256 }
257
258 /**
259 * Get the base pointer of the underlying array.
260 *
261 * @param array The input array (IN).
262 * @param array_type The C datatype of the array (IN).
263 *
264 * @returns ptr Pointer to the actual array.
265 *
266 * This function is helpful when you need to iterate through an
267 * entire array; simply get the base value of the array and use native
268 * C to iterate through it manually. This can have better performance
269 * than looping over OPAL_VALUE_ARRAY_GET_ITEM() and
270 * OPAL_VALUE_ARRAY_SET_ITEM() because it will [potentially] reduce the
271 * number of pointer dereferences.
272 */
273
274 #define OPAL_VALUE_ARRAY_GET_BASE(array, item_type) \
275 ((item_type*) ((array)->array_items))
276
277 END_C_DECLS
278
279 #endif
280
281