VirtualBox

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

最後變更 在這個檔案從32262是 32262,由 vboxsync 提交於 15 年 前

Main/linux/vector container: simplification

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.5 KB
 
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.alldomusa.eu.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/*** Helper macros and deinitions ***/
30
31/** The unit by which the vector capacity is increased */
32#define VECTOR_ALLOC_UNIT 16
33
34/** Calculate a hash of a string of tokens for sanity type checking */
35#define VECTOR_TOKEN_HASH(token) \
36 ((unsigned) \
37 ( VECTOR_TOKEN_HASH4(token, 0) \
38 ^ VECTOR_TOKEN_HASH4(token, 4) \
39 ^ VECTOR_TOKEN_HASH4(token, 8) \
40 ^ VECTOR_TOKEN_HASH4(token, 12)))
41
42/** Helper macro for @a VECTOR_TOKEN_HASH */
43#define VECTOR_TOKEN_HASH_VALUE(token, place, mul) \
44 (sizeof(#token) > place ? #token[place] * mul : 0)
45
46/** Helper macro for @a VECTOR_TOKEN_HASH */
47#define VECTOR_TOKEN_HASH4(token, place) \
48 VECTOR_TOKEN_HASH_VALUE(token, place, 0x1) \
49 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 1, 0x100) \
50 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 2, 0x10000) \
51 ^ VECTOR_TOKEN_HASH_VALUE(token, place + 3, 0x1000000)
52
53/** Generic vector structure, used by @a VECTOR_OBJ and @a VECTOR_PTR */
54#define VECTOR_STRUCT \
55{ \
56 /** The number of elements in the vector */ \
57 size_t mcElements; \
58 /** The current capacity of the vector */ \
59 size_t mcCapacity; \
60 /** The size of an element */ \
61 size_t mcbElement; \
62 /** Hash value of the element type */ \
63 unsigned muTypeHash; \
64 /** The elements themselves */ \
65 void *mpvaElements; \
66 /** Destructor for elements - takes a pointer to an element. */ \
67 void (*mpfnCleanup)(void *); \
68}
69
70/*** Structure definitions ***/
71
72/** A vector of values or objects */
73typedef struct VECTOR_OBJ VECTOR_STRUCT VECTOR_OBJ;
74
75/** A vector of pointer values. (A handy special case.) */
76typedef struct VECTOR_PTR VECTOR_STRUCT VECTOR_PTR;
77
78/** Convenience macro for annotating the type of the vector. Unfortunately the
79 * type name is only cosmetic. */
80/** @todo can we do something useful with the type? */
81#define VECTOR_OBJ(type) VECTOR_OBJ
82
83/** Convenience macro for annotating the type of the vector. Unfortunately the
84 * type name is only cosmetic. */
85#define VECTOR_PTR(type) VECTOR_PTR
86
87/*** Private helper functions and macros ***/
88
89#define VEC_GET_ELEMENT_OBJ(pvaElements, cbElement, cElement) \
90 ((void *)((char *)(pvaElements) + (cElement) * (cbElement)))
91
92#define VEC_GET_ELEMENT_PTR(pvaElements, cElement) \
93 (*(void **)VEC_GET_ELEMENT_OBJ(pvaElements, sizeof(void *), cElement))
94
95/** Default cleanup function that does nothing. */
96DECLINLINE(void) vecNoCleanup(void *pvElement)
97{
98 (void) pvElement;
99}
100
101/** Expand an existing vector, implementation */
102DECLINLINE(int) vecExpand(size_t *pcCapacity, void **ppvaElements,
103 size_t cbElement)
104{
105 size_t cOldCap, cNewCap;
106 void *pRealloc;
107
108 cOldCap = *pcCapacity;
109 cNewCap = cOldCap + VECTOR_ALLOC_UNIT;
110 pRealloc = RTMemRealloc(*ppvaElements, cNewCap * cbElement);
111 if (!pRealloc)
112 return VERR_NO_MEMORY;
113 *pcCapacity = cNewCap;
114 *ppvaElements = pRealloc;
115 return VINF_SUCCESS;
116}
117
118/** Expand an existing vector */
119#define VEC_EXPAND(pvec) vecExpand(&(pvec)->mcCapacity, &(pvec)->mpvaElements, \
120 (pvec)->mcbElement)
121
122/** Reset a vector, cleaning up all its elements. */
123DECLINLINE(void) vecClearObj(VECTOR_OBJ *pvec)
124{
125 unsigned i;
126
127 for (i = 0; i < pvec->mcElements; ++i)
128 pvec->mpfnCleanup(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements,
129 pvec->mcbElement, i));
130 pvec->mcElements = 0;
131}
132
133/** Reset a pointer vector, cleaning up all its elements. */
134DECLINLINE(void) vecClearPtr(VECTOR_PTR *pvec)
135{
136 unsigned i;
137
138 for (i = 0; i < pvec->mcElements; ++i)
139 pvec->mpfnCleanup(VEC_GET_ELEMENT_PTR(pvec->mpvaElements, i));
140 pvec->mcElements = 0;
141}
142
143/** Clean up a vector */
144DECLINLINE(void) vecCleanupObj(VECTOR_OBJ *pvec)
145{
146 vecClearObj(pvec);
147 RTMemFree(pvec->mpvaElements);
148 pvec->mpvaElements = NULL;
149}
150
151/** Clean up a pointer vector */
152DECLINLINE(void) vecCleanupPtr(VECTOR_PTR *pvec)
153{
154 vecClearPtr(pvec);
155 RTMemFree(pvec->mpvaElements);
156 pvec->mpvaElements = NULL;
157}
158
159/** Initialise a vector structure, implementation */
160#define VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup) \
161 pvec->mcElements = pvec->mcCapacity = 0; \
162 pvec->mcbElement = cbElement; \
163 pvec->muTypeHash = uTypeHash; \
164 pvec->mpfnCleanup = pfnCleanup ? pfnCleanup : vecNoCleanup; \
165 pvec->mpvaElements = NULL;
166
167/** Initialise a vector. */
168DECLINLINE(void) vecInitObj(VECTOR_OBJ *pvec, size_t cbElement,
169 unsigned uTypeHash, void (*pfnCleanup)(void *))
170{
171 VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup)
172}
173
174/** Initialise a pointer vector. */
175DECLINLINE(void) vecInitPtr(VECTOR_PTR *pvec, size_t cbElement,
176 unsigned uTypeHash, void (*pfnCleanup)(void *))
177{
178 VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup)
179}
180
181/** Add an element onto the end of a vector */
182DECLINLINE(int) vecPushBackObj(VECTOR_OBJ *pvec, unsigned uTypeHash,
183 void *pvElement)
184{
185 int rc2;
186 AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER);
187 if ( pvec->mcElements == pvec->mcCapacity
188 && RT_FAILURE((rc2 = VEC_EXPAND(pvec))))
189 return rc2;
190 memcpy(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements, pvec->mcbElement,
191 pvec->mcElements), pvElement, pvec->mcbElement);
192 ++pvec->mcElements;
193 return VINF_SUCCESS;
194}
195
196/** Add a pointer onto the end of a pointer vector */
197DECLINLINE(int) vecPushBackPtr(VECTOR_PTR *pvec, unsigned uTypeHash,
198 void *pv)
199{
200 int rc2;
201 AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER);
202 if ( pvec->mcElements == pvec->mcCapacity
203 && RT_FAILURE((rc2 = VEC_EXPAND(pvec))))
204 return rc2;
205 VEC_GET_ELEMENT_PTR(pvec->mpvaElements, pvec->mcElements) = pv;
206 ++pvec->mcElements;
207 return VINF_SUCCESS;
208}
209
210/*** Public interface macros ***/
211
212/**
213 * Initialise a vector structure. Always succeeds.
214 * @param pvec pointer to an uninitialised vector structure
215 * @param type the type of the objects in the vector. As this is
216 * hashed by the preprocessor use of space etc is
217 * important.
218 * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called
219 * on a pointer to a vector element when that element is
220 * dropped
221 */
222#define VEC_INIT_OBJ(pvec, type, pfnCleanup) \
223 vecInitObj(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \
224 (void (*)(void*)) pfnCleanup)
225
226/**
227 * Initialise a vector-of-pointers structure. Always succeeds.
228 * @param pvec pointer to an uninitialised vector structure
229 * @param type the type of the pointers in the vector, including the
230 * final "*". As this is hashed by the preprocessor use
231 * of space etc is important.
232 * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called
233 * directly on a vector element when that element is
234 * dropped
235 */
236#define VEC_INIT_PTR(pvec, type, pfnCleanup) \
237 vecInitPtr(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \
238 (void (*)(void*)) pfnCleanup)
239
240/**
241 * Clean up a vector.
242 * @param pvec pointer to the vector to clean up. The clean up function
243 * specified at initialisation (if any) is called for each element
244 * in the vector. After clean up, the vector structure is invalid
245 * until it is re-initialised
246 */
247#define VEC_CLEANUP_OBJ vecCleanupObj
248
249/**
250 * Clean up a vector-of-pointers.
251 * @param pvec pointer to the vector to clean up. The clean up function
252 * specified at initialisation (if any) is called for each element
253 * in the vector. After clean up, the vector structure is invalid
254 * until it is re-initialised
255 */
256#define VEC_CLEANUP_PTR vecCleanupPtr
257
258/**
259 * Reinitialises a vector structure to empty.
260 * @param pvec pointer to the vector to re-initialise. The clean up function
261 * specified at initialisation (if any) is called for each element
262 * in the vector.
263 */
264#define VEC_CLEAR_OBJ vecClearObj
265
266/**
267 * Reinitialises a vector-of-pointers structure to empty.
268 * @param pvec pointer to the vector to re-initialise. The clean up function
269 * specified at initialisation (if any) is called for each element
270 * in the vector.
271 */
272#define VEC_CLEAR_PTR vecClearPtr
273
274/**
275 * Adds an element to the back of a vector. The element will be byte-copied
276 * and become owned by the vector, to be cleaned up by the vector's clean-up
277 * routine when the element is dropped.
278 * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY)
279 * @returns VERR_INVALID_PARAMETER if the type does not match the type given
280 * when the vector was initialised (asserted)
281 * @param pvec pointer to the vector on to which the element should be
282 * added
283 * @param type the type of the vector as specified at initialisation.
284 * Spacing etc is important.
285 * @param pvElement void pointer to the element to be added
286 */
287#define VEC_PUSH_BACK_OBJ(pvec, type, pvElement) \
288 vecPushBackObj(pvec, VECTOR_TOKEN_HASH(type), \
289 (pvElement) + ((pvElement) - (type *)(pvElement)))
290
291/**
292 * Adds a pointer to the back of a vector-of-pointers. The pointer will become
293 * owned by the vector, to be cleaned up by the vector's clean-up routine when
294 * it is dropped.
295 * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY)
296 * @returns VERR_INVALID_PARAMETER if the type does not match the type given
297 * when the vector was initialised (asserted)
298 * @param pvec pointer to the vector on to which the element should be
299 * added
300 * @param type the type of the vector as specified at initialisation.
301 * Spacing etc is important.
302 * @param pvElement the pointer to be added, typecast to pointer-to-void
303 */
304#define VEC_PUSH_BACK_PTR(pvec, type, pvElement) \
305 vecPushBackPtr(pvec, VECTOR_TOKEN_HASH(type), \
306 (pvElement) + ((pvElement) - (type)(pvElement)))
307
308/**
309 * Returns the count of elements in a vector.
310 * @param pvec pointer to the vector.
311 */
312#define VEC_SIZE_OBJ(pvec) (pvec)->mcElements
313
314/**
315 * Returns the count of elements in a vector-of-pointers.
316 * @param pvec pointer to the vector.
317 */
318#define VEC_SIZE_PTR VEC_SIZE_OBJ
319
320/**
321 * Iterates over the vector elements from first to last and execute the
322 * following instruction or block on each iteration with @a pIterator set to
323 * point to the current element (that is, a pointer to the pointer element for
324 * a vector-of-pointers). Use in the same way as a "for" statement.
325 * @param pvec pointer to the vector to be iterated over
326 * @param type the type of the vector, must match the type specified at
327 * vector initialisation (including whitespace etc)
328 * @todo can we assert the correctness of the type in some way?
329 * @param pIterator a pointer to @a type which will be set to point to the
330 * current vector element on each iteration
331 */
332#define VEC_FOR_EACH(pvec, type, pIterator) \
333 for (pIterator = (type *) (pvec)->mpvaElements; \
334 (pvec)->muTypeHash == VECTOR_TOKEN_HASH(type) \
335 && pIterator < (type *) (pvec)->mpvaElements + (pvec)->mcElements; \
336 ++pIterator)
337
338#endif /* MAIN_VECTOR_H */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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