vector.c

Go to the documentation of this file.
00001 
00025 #include "vector.h"
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 
00030 // first, the private functions:
00031 
00044 #ifdef _MSC_VER
00045 __inline
00046 #else
00047 inline
00048 #endif
00049 static Bool Resize(Vector *vec, unsigned int newSize) {
00050     void *newArray;
00051     // try to allocate a new array and check for failure
00052     if ((newArray = realloc(vec->array, vec->itemSize * newSize)) == NULL) {
00053         // no memory
00054         return FALSE;
00055     }
00056     // keep the new array
00057     vec->array = newArray;
00058     // store the new size
00059     vec->size = newSize;
00060     // indicate success
00061     return TRUE;
00062 }
00063 
00076 #define Enlarge(vec, inc) \
00077     Resize(vec, \
00078     ((inc) > (vec)->size << 1) ? (inc) + ((vec)->size << 1) : (vec)->size << 1)
00079 
00088 #define Shrink(vec) \
00089     if (((vec)->size > (vec)->minSize) && \
00090         (((vec)->size >> 2) >= (vec)->items)) \
00091         Resize(vec, \
00092         ((vec)->size >> 1 > (vec)->minSize) ? (vec)->size >> 1 : (vec)->minSize)
00093 
00105 static void HeapMoveDown(Vector *vec, unsigned int index, void *temp) {
00106     void *child;
00107     unsigned int childInd;
00108     
00109     // requries use of the less than operation, so it must already be set
00110     assert(vec->lessOp != NULL);
00111     // loop through heap
00112     for (; (childInd = HEAP_CHILD_INDEX(index)) <= vec->items; index = childInd) {
00113         child = &(((char*)vec->array)[childInd * vec->itemSize]);
00114         if ((childInd < (vec->items - 1)) &&
00115         (*(vec->lessOp))(vec->itemSize + (char*)child, child)) {
00116             childInd++;
00117             child = (char*)child + vec->itemSize;
00118         }
00119         if ((*(vec->lessOp))(child, temp)) {
00120             memcpy(&((char *)vec->array)[index * vec->itemSize], child,
00121             vec->itemSize);
00122         }
00123         else
00124             break;
00125     }
00126     // found the spot to put the item temp
00127     memcpy(&(((char *)vec->array)[index * vec->itemSize]), temp, vec->itemSize);
00128 }
00129 
00130 
00131 // the public functions. These are commented in the header file.
00132 
00133 Bool VectorInit(Vector *vec, unsigned int initSize) {
00134     // the vector to initialize must exist
00135     assert(vec != NULL);
00136     // the initial size must be at least the minimum size
00137     assert(initSize >= vec->minSize);
00138     // allocate the array
00139     if ((vec->array = malloc(vec->itemSize * initSize)) == NULL) {
00140         // failed to create the array
00141         return FALSE;
00142     }
00143     #ifndef NDEBUG
00144     // make it easier to check that all data is initialized before being used
00145     // by putting crud in the array
00146     memset(vec->array, 0xCD, vec->itemSize * initSize);
00147     #endif
00148     // initialize the new vector's members
00149     vec->size  = initSize;
00150     vec->items = 0;
00151     // success!
00152     return TRUE;
00153 }
00154 
00155 void VectorDestroy(Vector *vec) {
00156     // check for items in the array and for a destructor function
00157     if (vec->destructOp && (vec->items > 0)) {
00158         void *item;
00159         unsigned int loop = vec->items;
00160         // loop through the items
00161         for (item = vec->array; loop > 0; loop--,
00162         item = (char*)item + vec->itemSize) {
00163             // call the destructor
00164             (*(vec->destructOp))(item);
00165         }
00166     }
00167     // deallocate the array
00168     if (vec->array != NULL) {
00169         free(vec->array);
00170     }
00171     #ifndef NDEBUG
00172     // put crud in vec to help catch improper use of vec after being destroyed
00173     memset(vec, 0xAB, sizeof(Vector));
00174     #endif
00175 }
00176 
00177 Bool VectorCopy(Vector *target, Vector *source){
00178     void *array;
00179     // attempt to allocate memory for the new copy
00180     if ((array = malloc(source->itemSize * source->size)) == NULL) {
00181         // couldn't get the memory
00182         return FALSE;
00183     }
00184     // copy the vector data
00185     *target = *source;
00186     // set the array
00187     target->array = array;
00188     // copy the items
00189     memcpy(target->array, source->array, source->itemSize * source->items);
00190     // success!
00191     return TRUE;
00192 }
00193 
00194 void VectorClear(Vector *vec) {
00195     // check for items in the array and for a destructor function
00196     if (vec->destructOp && (vec->items > 0)) {
00197         void *item;
00198         unsigned int loop = vec->items;
00199         // loop through the items
00200         for (item = vec->array; loop > 0; loop--,
00201         item = (char*)item + vec->itemSize) {
00202             // call the destructor
00203             (*(vec->destructOp))(item);
00204         }
00205     }
00206     // clear the item count
00207     vec->items = 0;
00208     // reduce the vector size if needed
00209     Shrink(vec);
00210 }
00211 
00212 void *VectorAdd(Vector *vec) {
00213     // check array size
00214     if (vec->items == vec->size) {
00215         // enlarge the array to take the new item
00216         if (!Resize(vec, vec->size << 1)) {
00217             // failure!
00218             return NULL;
00219         }
00220     }
00221     // make room for an item and send it back
00222     return &(((char *)vec->array)[vec->items++ * vec->itemSize]);
00223 }
00224 
00225 void *VectorPush(Vector *vec, void *item) {
00226     void *newItem;
00227     // check array size
00228     if (vec->items == vec->size) {
00229         // enlarge the array to take the new item
00230         if (!Resize(vec, vec->size << 1)) {
00231             // failure!
00232             return NULL;
00233         }
00234     }
00235     // add the item
00236     memcpy(newItem = &(((char *)vec->array)[vec->items++ * vec->itemSize]),
00237      item, vec->itemSize);
00238     // send it back
00239     return newItem;
00240 }
00241 
00242 void *VectorHeapPush(Vector *vec, void *item) {
00243     void *parent;
00244     unsigned int index = vec->items++, parentInd;
00245     // requries use of the less than operation, so it must already be set
00246     assert(vec->lessOp != NULL);
00247     // check array size
00248     if (vec->items == vec->size) {
00249         // enlarge the array to take the new item
00250         if (!Resize(vec, vec->size << 1)) {
00251             // failure!
00252             return NULL;
00253         }
00254     }
00255     for (; parentInd = HEAP_PARENT_INDEX(index),
00256     index && (*(vec->lessOp))(item,
00257     (parent = &((char *)vec->array)[parentInd * vec->itemSize]));
00258     index = parentInd) {
00259         // move item up
00260         memcpy(&(((char *)vec->array)[index * vec->itemSize]), parent,
00261         vec->itemSize);
00262     }
00263     // copy in the new item
00264     memcpy(parent = &(((char *)vec->array)[index * vec->itemSize]), item,
00265     vec->itemSize);
00266     return parent;
00267 }
00268 
00269 void VectorPop(Vector *vec) {
00270     // decrease size and check for removal from empty vector
00271     if (vec->items > 0) {
00272         vec->items--;
00273         // call the destructor
00274         if (vec->destructOp) {
00275             (*(vec->destructOp))
00276             (&(((char *)vec->array)[vec->items * vec->itemSize]));
00277         }
00278         // reduce the vector size if needed
00279         Shrink(vec);
00280     }
00281 }
00282 
00283 void VectorHeapPop(Vector *vec) {
00284     // decrease size and check for removal from empty vector
00285     if (vec->items > 0) {
00286         vec->items--;
00287         // call the destructor
00288         if (vec->destructOp) {
00289             (*(vec->destructOp))(vec->array);
00290         }
00291         // take the last item, now outside the heap, and move it through the
00292         //  heap to find it's new place
00293         HeapMoveDown(vec, 0,
00294         &(((char *)vec->array)[vec->items * vec->itemSize]));
00295         // reduce the vector size if needed
00296         Shrink(vec);
00297     }
00298 }
00299 
00300 void VectorHeapSort(Vector *vec) {
00301     void *lastItem;
00302     unsigned int items;
00303     #ifdef _MSC_VER
00304     // quick kludge fix for original code not working with MS VC++
00305     char tempVal[1024];
00306     assert(vec->itemSize <= 1024);
00307     #else
00308     char tempVal[vec->itemSize];
00309     #endif
00310     // check for items to sort
00311     if (vec->items == 0) return;
00312     // order the vector into a heap
00313     VectorMakeHeap(vec);
00314     // keep a local copy of the number of items
00315     items = vec->items--; // the first item is already sorted
00316     lastItem = &(((char *)vec->array)[vec->items * vec->itemSize]);
00317     // loop until sorted
00318     for (; vec->items < 0xFFFFFFFF;  vec->items--,
00319     lastItem = (char*)lastItem -  vec->itemSize) {
00320         // copy the last item into the temp spot
00321         memcpy(tempVal, lastItem, vec->itemSize);
00322         // copy the first item into the last
00323         memcpy(lastItem, vec->array, vec->itemSize);
00324         // put the temp item back into the heap
00325         HeapMoveDown(vec, 0, tempVal);
00326     }
00327     // restore the vector's item count
00328     vec->items = items;
00329 }
00330 
00331 void *VectorInsertMany(Vector *vec, unsigned int index, unsigned int count) {
00332     void *dest;
00333     unsigned int newSize = vec->items + count;
00334     // assure the given index is valid
00335     assert(index <= vec->items);
00336     // check array size
00337     if (newSize > vec->size) {
00338         // enlarge the array to take the new item
00339         if (!Enlarge(vec, newSize)) {
00340             // failure!
00341             return NULL;
00342         }
00343     }
00344     // get a pointer to the sport where the new items will go
00345     dest = &(((char *)vec->array)[index * vec->itemSize]);
00346     // copy everything
00347     memmove((char*)dest + count * vec->itemSize, dest,
00348      vec->itemSize * (vec->items - index));
00349     // set the new number of items
00350     vec->items = newSize;
00351     #ifndef NDEBUG
00352     // put crud in the new item
00353     memset(dest, 0xCD, vec->itemSize * count);
00354     #endif
00355     // send back the first item
00356     return dest;
00357 }
00358 
00359 void VectorRemoveMany(Vector *vec, unsigned int index, unsigned int count) {
00360     void *trg, *item;
00361     unsigned int loop;
00362     // assure the given index is valid
00363     assert(index < vec->items);
00364     // cannot remove more items than what are already in the vector
00365     assert(count <= (vec->items - index));
00366     // get a pointer to the item to be removed
00367     item = trg = &(((char *)vec->array)[index * vec->itemSize]);
00368     // check for a destructor
00369     if (vec->destructOp) {
00370         // loop through all the items to be removed
00371         for (loop = count; loop > 0; loop--, item = (char*)item + vec->itemSize) {
00372             // call the item's destructor
00373             (*vec->destructOp)(trg);
00374         }
00375     }
00376     else {
00377         // compute the address of the first item following what is removed
00378         item = (char*)trg + count * vec->itemSize;
00379     }
00380     // move the remaining items that follow the removed items forward in the
00381     // array
00382     memmove(trg, item, vec->itemSize * (vec->items - (index + count)));
00383     // update the number of items
00384     vec->items -= count;
00385     // reduce the vector size if needed
00386     Shrink(vec);
00387 }
00388 
00389 void VectorMakeHeap(Vector *vec) {
00390     unsigned int loop;
00391     void *item;
00392     #ifdef _MSC_VER
00393     // quick kludge fix for original code not working with MS VC++
00394     char tempVal[1024];
00395     assert(vec->itemSize <= 1024);
00396     #else
00397     char tempVal[vec->itemSize];
00398     #endif
00399     // check for items to heapify
00400     if (vec->items == 0) return;
00401     loop = vec->items >> 1;
00402     item = &(((char *)vec->array)[loop * vec->itemSize]);
00403     // loop through the array
00404     for (; loop < 0xFFFFFFFF; loop--, item = (char*)item - vec->itemSize) {
00405         // make a temp copy of the data at m_pArray[uLoop]
00406         memcpy(tempVal, item, vec->itemSize);
00407         // make this branch of the tree a heap
00408         HeapMoveDown(vec, loop, tempVal);
00409     }
00410 }
00411 
00412 Bool VectorReserve(Vector *vec, unsigned int size) {
00413     // see if the requested size is larger than the current size
00414     if (size > vec->size) {
00415         // Enlarge the array
00416         return Resize(vec, size);
00417     }
00418     // the array is already large enough
00419     return TRUE;
00420 }
00421 
00422 void GenericPointerFree(void *item) {
00423     if (*(char**)item != NULL) {
00424         free(*((void **)item));
00425     }
00426 }
00427 

Generated on Mon May 28 04:41:39 2007 for Retro Tank Super Attack by  doxygen 1.5.2