# SbList.h

    00001 #ifndef COIN_SBLIST_H
    00002 #define COIN_SBLIST_H
    00003
    00004 /**************************************************************************\
    00005  *
    00006  *  This file is part of the Coin 3D visualization library.
    00007  *  Copyright (C) 1998-2003 by Systems in Motion.  All rights reserved.
    00008  *
    00009  *  This library is free software; you can redistribute it and/or
    00010  *  modify it under the terms of the GNU General Public License
    00011  *  ("GPL") version 2 as published by the Free Software Foundation.
    00012  *  See the file LICENSE.GPL at the root directory of this source
    00013  *  distribution for additional information about the GNU GPL.
    00014  *
    00015  *  For using Coin with software that can not be combined with the GNU
    00016  *  GPL, and for taking advantage of the additional benefits of our
    00017  *  support services, please contact Systems in Motion about acquiring
    00018  *  a Coin Professional Edition License.
    00019  *
    00020  *  See <URL:http://www.coin3d.org> for  more information.
    00021  *
    00022  *  Systems in Motion, Teknobyen, Abels Gate 5, 7030 Trondheim, NORWAY.
    00023  *  <URL:http://www.sim.no>.
    00024  *
    00025 \**************************************************************************/
    00026
    00027 #include <Inventor/SbBasic.h>
    00028 #include <assert.h>
    00029 #include <stddef.h> // NULL definition
    00030
    00031 // We usually implement inline functions below the class definition,
    00032 // since we think that makes the file more readable. However, this is
    00033 // not done for this class, since Visual C++ is not too happy about
    00034 // having functions declared as inline for a template class.
    00035 // pederb, 2001-10-12
    00036
    00037 // FIXME: this is just a quick hack to avoid heaps of irritating
    00038 // warning messages from the compiler for client code compiled under
    00039 // MSVC++. Should try to find the real reason for the warnings and fix
    00040 // the cause of the problem instead. 20020730 mortene.
    00041 #ifdef _MSC_VER // Microsoft Visual C++
    00042 #pragma warning(disable:4251)
    00043 #pragma warning(disable:4275)
    00044 #endif // _MSC_VER
    00045
    00046 template <class Type>
    00047 class SbList {
    00048   // Older compilers aren't too happy about const declarations in the
    00049   // class definitions, so use the enum trick described by Scott
    00050   // Meyers in "Effective C++".
    00051   enum { DEFAULTSIZE = 4 };
    00052
    00053 public:
    00054
    00055   SbList(const int sizehint = DEFAULTSIZE)
    00056     : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
    00057     if (sizehint > DEFAULTSIZE) this->grow(sizehint);
    00058   }
    00059
    00060   SbList(const SbList<Type> & l)
    00061     : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
    00062     this->copy(l);
    00063   }
    00064
    00065   ~SbList() {
    00066     if (this->itembuffer != builtinbuffer) delete[] this->itembuffer;
    00067   }
    00068
    00069   void copy(const SbList<Type> & l) {
    00070     if (this == &l) return;
    00071     const int n = l.numitems;
    00072     this->expand(n);
    00073     for (int i = 0; i < n; i++) this->itembuffer[i] = l.itembuffer[i];
    00074   }
    00075
    00076   SbList <Type> & operator=(const SbList<Type> & l) {
    00077     this->copy(l);
    00078     return *this;
    00079   }
    00080
    00081   void fit(void) {
    00082     const int items = this->numitems;
    00083
    00084     if (items < this->itembuffersize) {
    00085       Type * newitembuffer = this->builtinbuffer;
    00086       if (items > DEFAULTSIZE) newitembuffer = new Type[items];
    00087
    00088       if (newitembuffer != this->itembuffer) {
    00089         for (int i = 0; i < items; i++) newitembuffer[i] = this->itembuffer[i];
    00090       }
    00091
    00092       if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
    00093       this->itembuffer = newitembuffer;
    00094       this->itembuffersize = items > DEFAULTSIZE ? items : DEFAULTSIZE;
    00095     }
    00096   }
    00097
    00098   void append(const Type item) {
    00099     if (this->numitems == this->itembuffersize) this->grow();
    00100     this->itembuffer[this->numitems++] = item;
    00101   }
    00102
    00103   int find(const Type item) const {
    00104     for (int i = 0; i < this->numitems; i++)
    00105       if (this->itembuffer[i] == item) return i;
    00106     return -1;
    00107   }
    00108
    00109   void insert(const Type item, const int insertbefore) {
    00110 #ifdef COIN_EXTRA_DEBUG
    00111     assert(insertbefore >= 0 && insertbefore <= this->numitems);
    00112 #endif // COIN_EXTRA_DEBUG
    00113     if (this->numitems == this->itembuffersize) this->grow();
    00114
    00115     for (int i = this->numitems; i > insertbefore; i--)
    00116       this->itembuffer[i] = this->itembuffer[i-1];
    00117     this->itembuffer[insertbefore] = item;
    00118     this->numitems++;
    00119   }
    00120
    00121   void removeItem(const Type item) {
    00122     int idx = this->find(item);
    00123 #ifdef COIN_EXTRA_DEBUG
    00124     assert(idx != -1);
    00125 #endif // COIN_EXTRA_DEBUG
    00126     this->remove(idx);
    00127   }
    00128
    00129   void remove(const int index) {
    00130 #ifdef COIN_EXTRA_DEBUG
    00131     assert(index >= 0 && index < this->numitems);
    00132 #endif // COIN_EXTRA_DEBUG
    00133     this->numitems--;
    00134     for (int i = index; i < this->numitems; i++)
    00135       this->itembuffer[i] = this->itembuffer[i + 1];
    00136   }
    00137
    00138   void removeFast(const int index) {
    00139 #ifdef COIN_EXTRA_DEBUG
    00140     assert(index >= 0 && index < this->numitems);
    00141 #endif // COIN_EXTRA_DEBUG
    00142     this->itembuffer[index] = this->itembuffer[--this->numitems];
    00143   }
    00144
    00145   int getLength(void) const {
    00146     return this->numitems;
    00147   }
    00148
    00149   void truncate(const int length, const int fit = 0) {
    00150 #ifdef COIN_EXTRA_DEBUG
    00151     assert(length <= this->numitems);
    00152 #endif // COIN_EXTRA_DEBUG
    00153     this->numitems = length;
    00154     if (fit) this->fit();
    00155   }
    00156
    00157   void push(const Type item) {
    00158     this->append(item);
    00159   }
    00160
    00161   Type pop(void) {
    00162 #ifdef COIN_EXTRA_DEBUG
    00163     assert(this->numitems > 0);
    00164 #endif // COIN_EXTRA_DEBUG
    00165     return this->itembuffer[--this->numitems];
    00166   }
    00167
    00168   const Type * getArrayPtr(const int start = 0) const {
    00169     return &this->itembuffer[start];
    00170   }
    00171
    00172   Type operator[](const int index) const {
    00173 #ifdef COIN_EXTRA_DEBUG
    00174     assert(index >= 0 && index < this->numitems);
    00175 #endif // COIN_EXTRA_DEBUG
    00176     return this->itembuffer[index];
    00177   }
    00178
    00179   Type & operator[](const int index) {
    00180 #ifdef COIN_EXTRA_DEBUG
    00181     assert(index >= 0 && index < this->numitems);
    00182 #endif // COIN_EXTRA_DEBUG
    00183     return this->itembuffer[index];
    00184   }
    00185
    00186   int operator==(const SbList<Type> & l) const {
    00187     if (this == &l) return TRUE;
    00188     if (this->numitems != l.numitems) return FALSE;
    00189     for (int i = 0; i < this->numitems; i++)
    00190       if (this->itembuffer[i] != l.itembuffer[i]) return FALSE;
    00191     return TRUE;
    00192   }
    00193
    00194   int operator!=(const SbList<Type> & l) const {
    00195     return !(*this == l);
    00196   }
    00197
    00198 protected:
    00199
    00200   void expand(const int size) {
    00201     this->grow(size);
    00202     this->numitems = size;
    00203   }
    00204
    00205   int getArraySize(void) const {
    00206     return this->itembuffersize;
    00207   }
    00208
    00209 private:
    00210   void grow(const int size = -1) {
    00211     // Default behavior is to double array size.
    00212     if (size == -1) this->itembuffersize <<= 1;
    00213     else if (size <= this->itembuffersize) return;
    00214     else { this->itembuffersize = size; }
    00215
    00216     Type * newbuffer = new Type[this->itembuffersize];
    00217     const int n = this->numitems;
    00218     for (int i = 0; i < n; i++) newbuffer[i] = this->itembuffer[i];
    00219     if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
    00220     this->itembuffer = newbuffer;
    00221   }
    00222
    00223   int itembuffersize;
    00224   int numitems;
    00225   Type * itembuffer;
    00226   Type builtinbuffer[DEFAULTSIZE];
    00227 };
    00228
    00229 #endif // !COIN_SBLIST_H