Open Dynamics Engine

array.h

00001 /*************************************************************************
00002  *                                                                       *
00003  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
00004  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
00005  *                                                                       *
00006  * This library is free software; you can redistribute it and/or         *
00007  * modify it under the terms of EITHER:                                  *
00008  *   (1) The GNU Lesser General Public License as published by the Free  *
00009  *       Software Foundation; either version 2.1 of the License, or (at  *
00010  *       your option) any later version. The text of the GNU Lesser      *
00011  *       General Public License is included with this library in the     *
00012  *       file LICENSE.TXT.                                               *
00013  *   (2) The BSD-style license that is included with this library in     *
00014  *       the file LICENSE-BSD.TXT.                                       *
00015  *                                                                       *
00016  * This library is distributed in the hope that it will be useful,       *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00019  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
00020  *                                                                       *
00021  *************************************************************************/
00022 
00023 /* this comes from the `reuse' library. copy any changes back to the source.
00024  *
00025  * Variable sized array template. The array is always stored in a contiguous
00026  * chunk. The array can be resized. A size increase will cause more memory
00027  * to be allocated, and may result in relocation of the array memory.
00028  * A size decrease has no effect on the memory allocation.
00029  *
00030  * Array elements with constructors or destructors are not supported!
00031  * But if you must have such elements, here's what to know/do:
00032  *   - Bitwise copy is used when copying whole arrays.
00033  *   - When copying individual items (via push(), insert() etc) the `='
00034  *     (equals) operator is used. Thus you should define this operator to do
00035  *     a bitwise copy. You should probably also define the copy constructor.
00036  */
00037 
00038 
00039 #ifndef _ODE_ARRAY_H_
00040 #define _ODE_ARRAY_H_
00041 
00042 #include <ode/odeconfig.h>
00043 
00044 
00045 // this base class has no constructors or destructor, for your convenience.
00046 
00047 class dArrayBase {
00048 protected:
00049   int _size;      // number of elements in `data'
00050   int _anum;      // allocated number of elements in `data'
00051   void *_data;    // array data
00052 
00053   void _freeAll (int sizeofT);
00054   void _setSize (int newsize, int sizeofT);
00055   // set the array size to `newsize', allocating more memory if necessary.
00056   // if newsize>_anum and is a power of two then this is guaranteed to
00057   // set _size and _anum to newsize.
00058 
00059 public:
00060   // not: dArrayBase () { _size=0; _anum=0; _data=0; }
00061 
00062   int size() const { return _size; }
00063   int allocatedSize() const { return _anum; }
00064   void * operator new (size_t size);
00065   void operator delete (void *ptr, size_t size);
00066 
00067   void constructor() { _size=0; _anum=0; _data=0; }
00068   // if this structure is allocated with malloc() instead of new, you can
00069   // call this to set it up.
00070 
00071   void constructLocalArray (int __anum);
00072   // this helper function allows non-reallocating arrays to be constructed
00073   // on the stack (or in the heap if necessary). this is something of a
00074   // kludge and should be used with extreme care. this function acts like
00075   // a constructor - it is called on uninitialized memory that will hold the
00076   // Array structure and the data. __anum is the number of elements that
00077   // are allocated. the memory MUST be allocated with size:
00078   //   sizeof(ArrayBase) + __anum*sizeof(T)
00079   // arrays allocated this way will never try to reallocate or free the
00080   // memory - that's your job.
00081 };
00082 
00083 
00084 template <class T> class dArray : public dArrayBase {
00085 public:
00086   void equals (const dArray<T> &x) {
00087     setSize (x.size());
00088     memcpy (_data,x._data,x._size * sizeof(T));
00089   }
00090 
00091   dArray () { constructor(); }
00092   dArray (const dArray<T> &x) { constructor(); equals (x); }
00093   ~dArray () { _freeAll(sizeof(T)); }
00094   void setSize (int newsize) { _setSize (newsize,sizeof(T)); }
00095   T *data() const { return (T*) _data; }
00096   T & operator[] (int i) const { return ((T*)_data)[i]; }
00097   void operator = (const dArray<T> &x) { equals (x); }
00098 
00099   void push (const T item) {
00100     if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
00101     memcpy (&(((T*)_data)[_size-1]), &item, sizeof(T));
00102   }
00103 
00104   void swap (dArray<T> &x) {
00105     int tmp1;
00106     void *tmp2;
00107     tmp1=_size; _size=x._size; x._size=tmp1;
00108     tmp1=_anum; _anum=x._anum; x._anum=tmp1;
00109     tmp2=_data; _data=x._data; x._data=tmp2;
00110   }
00111 
00112   // insert the item at the position `i'. if i<0 then add the item to the
00113   // start, if i >= size then add the item to the end of the array.
00114   void insert (int i, const T item) {
00115     if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
00116     if (i >= (_size-1)) i = _size-1;   // add to end
00117     else {
00118       if (i < 0) i=0;         // add to start
00119       int n = _size-1-i;
00120       if (n>0) memmove (((T*)_data) + i+1, ((T*)_data) + i, n*sizeof(T));
00121     }
00122     ((T*)_data)[i] = item;
00123   }
00124 
00125   void remove (int i) {
00126     if (i >= 0 && i < _size) {   // passing this test guarantees size>0
00127       int n = _size-1-i;
00128       if (n>0) memmove (((T*)_data) + i, ((T*)_data) + i+1, n*sizeof(T));
00129       _size--;
00130     }
00131   }
00132 };
00133 
00134 
00135 #endif