VirtualBox

source: vbox/trunk/src/VBox/Main/include/vector.h@ 47470

Last change on this file since 47470 was 32324, checked in by vboxsync, 14 years ago

Main/USBProxyServiceLinux: split out USB enumeration from USBProxyServiceLinux.cpp and HostHardwareLinux.cpp into a separate file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/** @file
2 * STL-inspired vector implementation in C
3 * @note functions in this file are inline to prevent warnings about
4 * unused static functions. I assume that in this day and age a
5 * compiler makes its own decisions about whether to actually
6 * inline a function.
7 * @note as this header is included in rdesktop-vrdp, we do not include other
8 * required header files here (to wit assert.h, err.h, mem.h and
9 * types.h). These must be included first. If this moves to iprt, we
10 * should write a wrapper around it doing that.
11 * @todo can we do more of the type checking at compile time somehow?
12 */
13
14/*
15 * Copyright (C) 2008-2010 Oracle Corporation
16 *
17 * This file is part of VirtualBox Open Source Edition (OSE), as
18 * available from http://www.virtualbox.org. This file is free software;
19 * you can redistribute it and/or modify it under the terms of the GNU
20 * General Public License (GPL) as published by the Free Software
21 * Foundation, in version 2 as it comes in the "COPYING" file of the
22 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
23 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
24 */
25
26#ifndef MAIN_VECTOR_H
27# define MAIN_VECTOR_H
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32
33#include <stdlib.h>
34
35/*******************************************************************************
36* Helper macros and definitions *
37*******************************************************************************/
38
39/** The unit by which the vector capacity is increased */
40#define VECTOR_ALLOC_UNIT 16
41
42/** Calculate a hash of a string of tokens for sanity type checking */
43#define VECTOR_TOKEN_HASH(token) \
44 ((unsigned) \
45 ( VECTOR_TOKEN_HASH4(token, 0) \
46 ^ VECTOR_TOKEN_HASH4(token, 4) \
47 ^ VECTOR_TOKEN_HASH4(token, 8) \
48 ^ VECTOR_TOKEN_HASH4(token, 12)))
49
50/** Helper macro for @a VECTOR_TOKEN_HASH */
51#define VECTOR_TOKEN_HASH_VALUE(token, place, mul) \
52 (sizeof(#token) > place ? #token[place] * mul : 0)
53
54/** Helper macro for @a VECTOR_TOKEN_HASH */
55#define VECTOR_TOKEN_HASH4(token, place) \
56 VECTOR_TOKEN_HASH_VALUE(token, place, 0x1) \
57 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 1, 0x100) \
58 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 2, 0x10000) \
59 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 3, 0x1000000)
60
61/** Generic vector structure, used by @a VECTOR_OBJ and @a VECTOR_PTR */
62#define VECTOR_STRUCT \
63{ \
64 /** The number of elements in the vector */ \
65 size_t mcElements; \
66 /** The current capacity of the vector */ \
67 size_t mcCapacity; \
68 /** The size of an element */ \
69 size_t mcbElement; \
70 /** Hash value of the element type */ \
71 unsigned muTypeHash; \
72 /** The elements themselves */ \
73 void *mpvaElements; \
74 /** Destructor for elements - takes a pointer to an element. */ \
75 void (*mpfnCleanup)(void *); \
76}
77
78/*** Structure definitions ***/
79
80/** A vector of values or objects */
81typedef struct VECTOR_OBJ VECTOR_STRUCT VECTOR_OBJ;
82
83/** A vector of pointer values. (A handy special case.) */
84typedef struct VECTOR_PTR VECTOR_STRUCT VECTOR_PTR;
85
86/** Convenience macro for annotating the type of the vector. Unfortunately the
87 * type name is only cosmetic. */
88/** @todo can we do something useful with the type? */
89#define VECTOR_OBJ(type) VECTOR_OBJ
90
91/** Convenience macro for annotating the type of the vector. Unfortunately the
92 * type name is only cosmetic. */
93#define VECTOR_PTR(type) VECTOR_PTR
94
95/*** Private helper functions and macros ***/
96
97#define VEC_GET_ELEMENT_OBJ(pvaElements, cbElement, cElement) \
98 ((void *)((char *)(pvaElements) + (cElement) * (cbElement)))
99
100#define VEC_GET_ELEMENT_PTR(pvaElements, cElement) \
101 (*(void **)VEC_GET_ELEMENT_OBJ(pvaElements, sizeof(void *), cElement))
102
103/** Default cleanup function that does nothing. */
104DECLINLINE(void) vecNoCleanup(void *pvElement)
105{
106 (void) pvElement;
107}
108
109/** Expand an existing vector, implementation */
110DECLINLINE(int) vecExpand(size_t *pcCapacity, void **ppvaElements,
111 size_t cbElement)
112{
113 size_t cOldCap, cNewCap;
114 void *pRealloc;
115
116 cOldCap = *pcCapacity;
117 cNewCap = cOldCap + VECTOR_ALLOC_UNIT;
118 pRealloc = RTMemRealloc(*ppvaElements, cNewCap * cbElement);
119 if (!pRealloc)
120 return VERR_NO_MEMORY;
121 *pcCapacity = cNewCap;
122 *ppvaElements = pRealloc;
123 return VINF_SUCCESS;
124}
125
126/** Expand an existing vector */
127#define VEC_EXPAND(pvec) vecExpand(&(pvec)->mcCapacity, &(pvec)->mpvaElements, \
128 (pvec)->mcbElement)
129
130/** Reset a vector, cleaning up all its elements. */
131DECLINLINE(void) vecClearObj(VECTOR_OBJ *pvec)
132{
133 unsigned i;
134
135 for (i = 0; i < pvec->mcElements; ++i)
136 pvec->mpfnCleanup(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements,
137 pvec->mcbElement, i));
138 pvec->mcElements = 0;
139}
140
141/** Reset a pointer vector, cleaning up all its elements. */
142DECLINLINE(void) vecClearPtr(VECTOR_PTR *pvec)
143{
144 unsigned i;
145
146 for (i = 0; i < pvec->mcElements; ++i)
147 pvec->mpfnCleanup(VEC_GET_ELEMENT_PTR(pvec->mpvaElements, i));
148 pvec->mcElements = 0;
149}
150
151/** Clean up a vector */
152DECLINLINE(void) vecCleanupObj(VECTOR_OBJ *pvec)
153{
154 vecClearObj(pvec);
155 RTMemFree(pvec->mpvaElements);
156 pvec->mpvaElements = NULL;
157}
158
159/** Clean up a pointer vector */
160DECLINLINE(void) vecCleanupPtr(VECTOR_PTR *pvec)
161{
162 vecClearPtr(pvec);
163 RTMemFree(pvec->mpvaElements);
164 pvec->mpvaElements = NULL;
165}
166
167/** Initialise a vector structure, implementation */
168#define VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup) \
169 pvec->mcElements = pvec->mcCapacity = 0; \
170 pvec->mcbElement = cbElement; \
171 pvec->muTypeHash = uTypeHash; \
172 pvec->mpfnCleanup = pfnCleanup ? pfnCleanup : vecNoCleanup; \
173 pvec->mpvaElements = NULL;
174
175/** Initialise a vector. */
176DECLINLINE(void) vecInitObj(VECTOR_OBJ *pvec, size_t cbElement,
177 unsigned uTypeHash, void (*pfnCleanup)(void *))
178{
179 VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup)
180}
181
182/** Initialise a pointer vector. */
183DECLINLINE(void) vecInitPtr(VECTOR_PTR *pvec, size_t cbElement,
184 unsigned uTypeHash, void (*pfnCleanup)(void *))
185{
186 VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup)
187}
188
189/** Add an element onto the end of a vector */
190DECLINLINE(int) vecPushBackObj(VECTOR_OBJ *pvec, unsigned uTypeHash,
191 void *pvElement)
192{
193 int rc2;
194 AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER);
195 if ( pvec->mcElements == pvec->mcCapacity
196 && RT_FAILURE((rc2 = VEC_EXPAND(pvec))))
197 return rc2;
198 memcpy(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements, pvec->mcbElement,
199 pvec->mcElements), pvElement, pvec->mcbElement);
200 ++pvec->mcElements;
201 return VINF_SUCCESS;
202}
203
204/** Add a pointer onto the end of a pointer vector */
205DECLINLINE(int) vecPushBackPtr(VECTOR_PTR *pvec, unsigned uTypeHash,
206 void *pv)
207{
208 int rc2;
209 AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER);
210 if ( pvec->mcElements == pvec->mcCapacity
211 && RT_FAILURE((rc2 = VEC_EXPAND(pvec))))
212 return rc2;
213 VEC_GET_ELEMENT_PTR(pvec->mpvaElements, pvec->mcElements) = pv;
214 ++pvec->mcElements;
215 return VINF_SUCCESS;
216}
217
218/*******************************************************************************
219* Public interface macros *
220*******************************************************************************/
221
222/**
223 * Initialise a vector structure. Always succeeds.
224 * @param pvec pointer to an uninitialised vector structure
225 * @param type the type of the objects in the vector. As this is
226 * hashed by the preprocessor use of space etc is
227 * important.
228 * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called
229 * on a pointer to a vector element when that element is
230 * dropped
231 */
232#define VEC_INIT_OBJ(pvec, type, pfnCleanup) \
233 vecInitObj(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \
234 (void (*)(void*)) pfnCleanup)
235
236/**
237 * Initialise a vector-of-pointers structure. Always succeeds.
238 * @param pvec pointer to an uninitialised vector structure
239 * @param type the type of the pointers in the vector, including the
240 * final "*". As this is hashed by the preprocessor use
241 * of space etc is important.
242 * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called
243 * directly on a vector element when that element is
244 * dropped
245 */
246#define VEC_INIT_PTR(pvec, type, pfnCleanup) \
247 vecInitPtr(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \
248 (void (*)(void*)) pfnCleanup)
249
250/**
251 * Clean up a vector.
252 * @param pvec pointer to the vector to clean up. The clean up function
253 * specified at initialisation (if any) is called for each element
254 * in the vector. After clean up, the vector structure is invalid
255 * until it is re-initialised
256 */
257#define VEC_CLEANUP_OBJ vecCleanupObj
258
259/**
260 * Clean up a vector-of-pointers.
261 * @param pvec pointer to the vector to clean up. The clean up function
262 * specified at initialisation (if any) is called for each element
263 * in the vector. After clean up, the vector structure is invalid
264 * until it is re-initialised
265 */
266#define VEC_CLEANUP_PTR vecCleanupPtr
267
268/**
269 * Reinitialises a vector structure to empty.
270 * @param pvec pointer to the vector to re-initialise. The clean up function
271 * specified at initialisation (if any) is called for each element
272 * in the vector.
273 */
274#define VEC_CLEAR_OBJ vecClearObj
275
276/**
277 * Reinitialises a vector-of-pointers structure to empty.
278 * @param pvec pointer to the vector to re-initialise. The clean up function
279 * specified at initialisation (if any) is called for each element
280 * in the vector.
281 */
282#define VEC_CLEAR_PTR vecClearPtr
283
284/**
285 * Adds an element to the back of a vector. The element will be byte-copied
286 * and become owned by the vector, to be cleaned up by the vector's clean-up
287 * routine when the element is dropped.
288 * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY)
289 * @returns VERR_INVALID_PARAMETER if the type does not match the type given
290 * when the vector was initialised (asserted)
291 * @param pvec pointer to the vector on to which the element should be
292 * added
293 * @param type the type of the vector as specified at initialisation.
294 * Spacing etc is important.
295 * @param pvElement void pointer to the element to be added
296 */
297#define VEC_PUSH_BACK_OBJ(pvec, type, pvElement) \
298 vecPushBackObj(pvec, VECTOR_TOKEN_HASH(type), \
299 (pvElement) + ((pvElement) - (type *)(pvElement)))
300
301/**
302 * Adds a pointer to the back of a vector-of-pointers. The pointer will become
303 * owned by the vector, to be cleaned up by the vector's clean-up routine when
304 * it is dropped.
305 * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY)
306 * @returns VERR_INVALID_PARAMETER if the type does not match the type given
307 * when the vector was initialised (asserted)
308 * @param pvec pointer to the vector on to which the element should be
309 * added
310 * @param type the type of the vector as specified at initialisation.
311 * Spacing etc is important.
312 * @param pvElement the pointer to be added, typecast to pointer-to-void
313 */
314#define VEC_PUSH_BACK_PTR(pvec, type, pvElement) \
315 vecPushBackPtr(pvec, VECTOR_TOKEN_HASH(type), \
316 (pvElement) + ((pvElement) - (type)(pvElement)))
317
318/**
319 * Returns the count of elements in a vector.
320 * @param pvec pointer to the vector.
321 */
322#define VEC_SIZE_OBJ(pvec) (pvec)->mcElements
323
324/**
325 * Returns the count of elements in a vector-of-pointers.
326 * @param pvec pointer to the vector.
327 */
328#define VEC_SIZE_PTR VEC_SIZE_OBJ
329
330/**
331 * Iterates over the vector elements from first to last and execute the
332 * following instruction or block on each iteration with @a pIterator set to
333 * point to the current element (that is, a pointer to the pointer element for
334 * a vector-of-pointers). Use in the same way as a "for" statement.
335 * @param pvec pointer to the vector to be iterated over
336 * @param type the type of the vector, must match the type specified at
337 * vector initialisation (including whitespace etc)
338 * @todo can we assert the correctness of the type in some way?
339 * @param pIterator a pointer to @a type which will be set to point to the
340 * current vector element on each iteration
341 */
342#define VEC_FOR_EACH(pvec, type, pIterator) \
343 for (pIterator = (type *) (pvec)->mpvaElements; \
344 (pvec)->muTypeHash == VECTOR_TOKEN_HASH(type) \
345 && pIterator < (type *) (pvec)->mpvaElements + (pvec)->mcElements; \
346 ++pIterator)
347
348#endif /* MAIN_VECTOR_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette