VirtualBox

Changeset 36805 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Apr 21, 2011 9:48:52 PM (14 years ago)
Author:
vboxsync
Message:

Additions/x11/seamless: yet another STL-vector-in-C

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
1 added
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk

    r35380 r36805  
    108108        $(QUIET)$(APPEND) -t "$@" "done"
    109109
     110   PROGRAMS += tstVector
     111   tstVector_TEMPLATE = VBOXR3TSTEXE
     112   tstVector_SOURCES = \
     113           testcase/tstVector.cpp
     114   tstVector_INCS = .
     115   tstVector_LIBS = \
     116           $(LIB_RUNTIME)
     117
    110118   #
    111119   # Additional testcase designed to be run manually, which initiates and starts the Linux
  • trunk/src/VBox/Additions/x11/VBoxClient/vector.h

    r36670 r36805  
    11/** @file
     2 * IPRT - Vector
    23 * 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?
    124 */
    135
    146/*
    15  * Copyright (C) 2008-2010 Oracle Corporation
     7 * Copyright (C) 2011 Oracle Corporation
    168 *
    179 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2214 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    2315 * 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
     16 *
     17 * The contents of this file may alternatively be used under the terms
     18 * of the Common Development and Distribution License Version 1.0
     19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
     20 * VirtualBox OSE distribution, in which case the provisions of the
     21 * CDDL are applicable instead of those of the GPL.
     22 *
     23 * You may elect to license modified versions of this file under the
     24 * terms and conditions of either the GPL or the CDDL or both.
     25 */
     26
     27/**
     28 * @todo the right Doxygen tag here
     29 * This file defines a set of macros which provide a functionality and an
     30 * interface roughly similar to the C++ STL vector container.  To create a
     31 * vector of a particular type one must first explicitly instantiate such a
     32 * vector in the source file, e.g.
     33 *   RTVEC_DECL(TopLevels, Window *)
     34 * without a semi-colon.  This macro will define a structure (struct TopLevels)
     35 * which contains a dynamically resizeable array of Window * elements.  It
     36 * will also define a number of inline methods for manipulating the structure,
     37 * such as
     38 *   Window *TopLevelsPushBack(struct TopLevels *)
     39 * which adds a new element to the end of the array and returns it, optionally
     40 * reallocating the array if there is not enough space for the new element.
     41 * (This particular method prototype differs from the STL equivalent -
     42 * push_back - more than most of the other methods).
     43 *
     44 * To create a vector, one simply needs to declare the structure, in this case
     45 *   struct TopLevels = RTVEC_INITIALIZER;
     46 *
     47 * There are various other macros for declaring vectors with different
     48 * allocators (e.g. RTVEC_DECL_ALLOCATOR) or with clean-up functions
     49 * (e.g. RTVEC_DECL_DELETE).  See the descriptions of the generic methods and
     50 * the declarator macros below.
     51 *
     52 * One particular use of vectors is to assemble an array of a particular type
     53 * in heap memory without knowing - or counting - the number of elements in
     54 * advance.  To do this, add the elements onto the array using PushBack, then
     55 * extract the array from the vector using the (non-STL) Detach method.
     56 *
     57 * @note functions in this file are inline to prevent warnings about
     58 *       unused static functions.  I assume that in this day and age a
     59 *       compiler makes its own decisions about whether to actually
     60 *       inline a function.
     61 * @note since vector structures must be explicitly instanciated unlike the
     62 *       C++ vector template, care must be taken not to instanciate a
     63 *       particular type twice, e.g. once in a header and once in a code file.
     64 *       Only using vectors in code files and keeping them out of interfaces
     65 *       (or passing them as anonymously) makes it easier to take care of this.
     66 */
     67#ifndef ___iprt_vector_h
     68# define ___iprt_vector_h
    2869
    2970/*******************************************************************************
     
    3172*******************************************************************************/
    3273
    33 #include <stdlib.h>
    34 
    35 /*******************************************************************************
    36 *   Helper macros and definitions                                              *
    37 *******************************************************************************/
     74#include <iprt/assert.h>
     75#include <iprt/cdefs.h>
     76#include <iprt/err.h>
     77#include <iprt/mem.h>  /** @todo Should the caller include this if they need
     78                        *        it? */
     79
     80
     81/**
     82 * Generic vector structure
     83 */
     84/** @todo perhaps we should include an additional member for a parameter to
     85 * three-argument reallocators, so that we can support e.g. mempools? */
     86#define RTVEC_DECL_STRUCT(name, type)                                      \
     87struct name                                                                \
     88{                                                                          \
     89    /** The number of elements in the vector */                            \
     90    size_t mcElements;                                                     \
     91    /** The current capacity of the vector */                              \
     92    size_t mcCapacity;                                                     \
     93    /** The elements themselves */                                         \
     94    type *mpElements;                                                      \
     95};
     96
     97/** Initialiser for an empty vector structure */
     98#define RTVEC_INITIALIZER { 0, 0, NULL }
    3899
    39100/** 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 */
    81 typedef struct VECTOR_OBJ VECTOR_STRUCT VECTOR_OBJ;
    82 
    83 /** A vector of pointer values.  (A handy special case.) */
    84 typedef 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. */
    104 DECLINLINE(void) vecNoCleanup(void *pvElement)
     101#define RTVECIMPL_ALLOC_UNIT 16
     102
     103/**
     104 * Generic method - get the size of a vector
     105 */
     106/** @todo What is the correct way to do doxygen for this sort of macro? */
     107#define RTVEC_DECLFN_SIZE(name, type)                                      \
     108DECLINLINE(size_t) name ## Size(struct name *pVec)                         \
     109{                                                                          \
     110    return(pVec->mcElements);                                              \
     111}
     112
     113/**
     114 * Generic method - expand a vector
     115 */
     116#define RTVEC_DECLFN_RESERVE(name, type, pfnRealloc)                       \
     117DECLINLINE(int) name ## Reserve(struct name *pVec, size_t cNewCapacity)    \
     118{                                                                          \
     119    void *pvNew;                                                           \
     120                                                                           \
     121    if (cNewCapacity <= pVec->mcCapacity)                                  \
     122        return VINF_SUCCESS;                                               \
     123    pvNew = pfnRealloc(pVec->mpElements, cNewCapacity * sizeof(type));     \
     124    if (!pvNew)                                                            \
     125        return VERR_NO_MEMORY;                                             \
     126    pVec->mcCapacity = cNewCapacity;                                       \
     127    pVec->mpElements = (type *)pvNew;                                      \
     128    return VINF_SUCCESS;                                                   \
     129}
     130
     131/**
     132 * Generic method - return a pointer to the first element in the vector.
     133 */
     134#define RTVEC_DECLFN_BEGIN(name, type)                                     \
     135DECLINLINE(type *) name ## Begin(struct name *pVec)                        \
     136{                                                                          \
     137    return(pVec->mpElements);                                              \
     138}
     139
     140/**
     141 * Generic method - return a pointer to one past the last element in the
     142 * vector.
     143 */
     144#define RTVEC_DECLFN_END(name, type)                                       \
     145DECLINLINE(type *) name ## End(struct name *pVec)                          \
     146{                                                                          \
     147    return(&pVec->mpElements[pVec->mcElements]);                           \
     148}
     149
     150/**
     151 * Generic method - add a new, uninitialised element onto a vector and return
     152 * it.
     153 * @note this method differs from the STL equivalent by letting the caller
     154 *       post-initialise the new element rather than copying it from its
     155 *       argument.
     156 */
     157#define RTVEC_DECLFN_PUSHBACK(name, type)                                  \
     158DECLINLINE(type *) name ## PushBack(struct name *pVec)                     \
     159{                                                                          \
     160    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     161    if (   pVec->mcElements == pVec->mcCapacity                            \
     162        && RT_FAILURE(name ## Reserve(pVec,   pVec->mcCapacity             \
     163                                            + RTVECIMPL_ALLOC_UNIT)))      \
     164        return NULL;                                                       \
     165    ++pVec->mcElements;                                                    \
     166    return &pVec->mpElements[pVec->mcElements - 1];                        \
     167}
     168
     169/**
     170 * Generic method - drop the last element from the vector.
     171 */
     172#define RTVEC_DECLFN_POPBACK(name)                                         \
     173DECLINLINE(void) name ## PopBack(struct name *pVec)                        \
     174{                                                                          \
     175    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     176    --pVec->mcElements;                                                    \
     177}
     178
     179/**
     180 * Generic method - drop the last element from the vector, calling a clean-up
     181 * method first.
     182 *
     183 * By taking an adapter function for the element to be dropped as an
     184 * additional macro parameter we can support clean-up by pointer
     185 * (pfnAdapter maps T* -> T*) or by value (maps T* -> T).  pfnAdapter takes
     186 * one argument of type @a type * and must return whatever type pfnDelete
     187 * expects.
     188 */
     189/** @todo find a better name for pfnAdapter? */
     190#define RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, pfnAdapter)     \
     191DECLINLINE(void) name ## PopBack(struct name *pVec)                        \
     192{                                                                          \
     193    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     194    --pVec->mcElements;                                                    \
     195    pfnDelete(pfnAdapter(&pVec->mpElements[pVec->mcElements]));            \
     196}
     197
     198/**
     199 * Generic method - reset a vector to empty.
     200 * @note This function does not free any memory
     201 */
     202#define RTVEC_DECLFN_CLEAR(name)                                           \
     203DECLINLINE(void) name ## Clear(struct name *pVec)                          \
     204{                                                                          \
     205    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     206    pVec->mcElements = 0;                                                  \
     207}
     208
     209/**
     210 * Generic method - reset a vector to empty, calling a clean-up method on each
     211 * element first.
     212 * @note See @a RTVEC_DECLFN_POPBACK_DELETE for an explanation of pfnAdapter
     213 * @note This function does not free any memory
     214 * @note The cleanup function is currently called on the elements from first
     215 *       to last.  The testcase expects this.
     216 */
     217#define RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, pfnAdapter)             \
     218DECLINLINE(void) name ## Clear(struct name *pVec)                          \
     219{                                                                          \
     220    size_t i;                                                              \
     221                                                                           \
     222    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     223    for (i = 0; i < pVec->mcElements; ++i)                                 \
     224        pfnDelete(pfnAdapter(&pVec->mpElements[i]));                       \
     225    pVec->mcElements = 0;                                                  \
     226}
     227
     228/**
     229 * Generic method - detach the array contained inside a vector and reset the
     230 * vector to empty.
     231 * @note This function does not free any memory
     232 */
     233#define RTVEC_DECLFN_DETACH(name, type)                                    \
     234DECLINLINE(type *) name ## Detach(struct name *pVec)                       \
     235{                                                                          \
     236    type *pArray = pVec->mpElements;                                       \
     237                                                                           \
     238    Assert(pVec->mcElements <= pVec->mcCapacity);                          \
     239    pVec->mcElements = 0;                                                  \
     240    pVec->mpElements = NULL;                                               \
     241    pVec->mcCapacity = 0;                                                  \
     242    return pArray;                                                         \
     243}
     244
     245/** Common declarations for all vector types */
     246#define RTVEC_DECL_COMMON(name, type, pfnRealloc)                          \
     247    RTVEC_DECL_STRUCT(name, type)                                          \
     248    RTVEC_DECLFN_SIZE(name, type)                                          \
     249    RTVEC_DECLFN_RESERVE(name, type, pfnRealloc)                           \
     250    RTVEC_DECLFN_BEGIN(name, type)                                         \
     251    RTVEC_DECLFN_END(name, type)                                           \
     252    RTVEC_DECLFN_PUSHBACK(name, type)                                      \
     253    RTVEC_DECLFN_DETACH(name, type)
     254
     255/**
     256 * Declarator macro - declare a vector type
     257 * @param  name        the name of the C struct type describing the vector as
     258 *                     well as the prefix of the functions for manipulating it
     259 * @param  type        the type of the objects contained in the vector
     260 * @param  pfnRealloc  the memory reallocation function used for expanding the
     261 *                     vector
     262 */
     263#define RTVEC_DECL_ALLOCATOR(name, type, pfnRealloc)                       \
     264    RTVEC_DECL_COMMON(name, type, pfnRealloc)                              \
     265    RTVEC_DECLFN_POPBACK(name)                                             \
     266    RTVEC_DECLFN_CLEAR(name)
     267
     268/**
     269 * Generic method - inline id mapping delete adapter function - see the
     270 * explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE.
     271 */
     272#define RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type)                         \
     273DECLINLINE(type *) name ## DeleteAdapterId(type *arg)                      \
     274{                                                                          \
     275    return arg;                                                            \
     276}
     277
     278/**
     279 * Generic method - inline pointer-to-value mapping delete adapter function -
     280 * see the explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE.
     281 */
     282#define RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type)                   \
     283DECLINLINE(type) name ## DeleteAdapterToValue(type *arg)                   \
     284{                                                                          \
     285    return *arg;                                                           \
     286}
     287
     288/**
     289 * Declarator macro - declare a vector type with a cleanup callback to be used
     290 * when elements are dropped from the vector.  The callback takes a pointer to
     291 * @a type,
     292 * NOT a value of type @a type.
     293 * @param  name        the name of the C struct type describing the vector as
     294 *                     well as the prefix of the functions for manipulating it
     295 * @param  type        the type of the objects contained in the vector
     296 * @param  pfnRealloc  the memory reallocation function used for expanding the
     297 *                     vector
     298 * @param  pfnDelete   the cleanup callback function - signature
     299 *                     void pfnDelete(type *)
     300 */
     301#define RTVEC_DECL_ALLOCATOR_DELETE(name, type, pfnRealloc, pfnDelete)     \
     302    RTVEC_DECL_COMMON(name, type, pfnRealloc)                              \
     303    RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type)                             \
     304    RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete,                     \
     305                                name ## DeleteAdapterId)                   \
     306    RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, name ## DeleteAdapterId)
     307
     308/**
     309 * Declarator macro - declare a vector type with a cleanup callback to be used
     310 * when elements are dropped from the vector.  The callback takes a parameter
     311 * of type @a type, NOT a pointer to @a type.
     312 * @param  name        the name of the C struct type describing the vector as
     313 *                     well as the prefix of the functions for manipulating it
     314 * @param  type        the type of the objects contained in the vector
     315 * @param  pfnRealloc  the memory reallocation function used for expanding the
     316 *                     vector
     317 * @param  pfnDelete   the cleanup callback function - signature
     318 *                     void pfnDelete(type)
     319 */
     320#define RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, pfnRealloc,       \
     321                                             pfnDelete)                    \
     322    RTVEC_DECL_COMMON(name, type, pfnRealloc)                              \
     323    RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type)                       \
     324    RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete,                     \
     325                                name ## DeleteAdapterToValue)              \
     326    RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete,                             \
     327                              name ## DeleteAdapterToValue)
     328
     329/**
     330 * Inline wrapper around RTMemRealloc macro to get a function usable as a
     331 * callback.
     332 */
     333DECLINLINE(void *) rtvecReallocDefTag(void *pv, size_t cbNew)
    105334{
    106     (void) pvElement;
    107 }
    108 
    109 /** Expand an existing vector, implementation */
    110 DECLINLINE(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. */
    131 DECLINLINE(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. */
    142 DECLINLINE(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 */
    152 DECLINLINE(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 */
    160 DECLINLINE(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. */
    176 DECLINLINE(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. */
    183 DECLINLINE(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 */
    190 DECLINLINE(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 */
    205 DECLINLINE(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 */
     335    return RTMemRealloc(pv, cbNew);
     336}
     337
     338/**
     339 * Declarator macro - declare a vector type (see @a RTVEC_DECL_ALLOCATOR)
     340 * using RTMemRealloc as a memory allocator
     341 * @param  name        the name of the C struct type describing the vector as
     342 *                     well as the prefix of the functions for manipulating it
     343 * @param  type        the type of the objects contained in the vector
     344 */
     345#define RTVEC_DECL(name, type)                                             \
     346    RTVEC_DECL_ALLOCATOR(name, type, rtvecReallocDefTag)
     347
     348/**
     349 * Declarator macro - declare a vector type with a cleanup by pointer callback
     350 * (see @a RTVEC_DECL_ALLOCATOR_DELETE) using RTMemRealloc as a memory
     351 * allocator
     352 * @param  name        the name of the C struct type describing the vector as
     353 *                     well as the prefix of the functions for manipulating it
     354 * @param  type        the type of the objects contained in the vector
     355 * @param  pfnDelete   the cleanup callback function - signature
     356 *                     void pfnDelete(type *)
     357 */
     358#define RTVEC_DECL_DELETE(name, type, pfnDelete)                           \
     359    RTVEC_DECL_ALLOCATOR_DELETE(name, type, rtvecReallocDefTag, pfnDelete)
     360
     361/**
     362 * Declarator macro - declare a vector type with a cleanup by value callback
     363 * (see @a RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE) using RTMemRealloc as a memory
     364 * allocator
     365 * @param  name        the name of the C struct type describing the vector as
     366 *                     well as the prefix of the functions for manipulating it
     367 * @param  type        the type of the objects contained in the vector
     368 * @param  pfnDelete   the cleanup callback function - signature
     369 *                     void pfnDelete(type)
     370 */
     371#define RTVEC_DECL_DELETE_BY_VALUE(name, type, pfnDelete)                  \
     372    RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, rtvecReallocDefTag,   \
     373                                         pfnDelete)
     374
     375#endif /* ___iprt_vector_h */
Note: See TracChangeset for help on using the changeset viewer.

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