1 /**************************************************************************\
2  *
3  *  This file is part of the Coin 3D visualization library.
4  *  Copyright (C) by Kongsberg Oil & Gas Technologies.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  ("GPL") version 2 as published by the Free Software Foundation.
9  *  See the file LICENSE.GPL at the root directory of this source
10  *  distribution for additional information about the GNU GPL.
11  *
12  *  For using Coin with software that can not be combined with the GNU
13  *  GPL, and for taking advantage of the additional benefits of our
14  *  support services, please contact Kongsberg Oil & Gas Technologies
15  *  about acquiring a Coin Professional Edition License.
16  *
17  *  See http://www.coin3d.org/ for more information.
18  *
19  *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
20  *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
21  *
22 \**************************************************************************/
23 
24 #ifndef SOGUI_SBGUILIST_H
25 #define SOGUI_SBGUILIST_H
26 
27 /**************************************************************************/
28 
29 // IMPORTANT NOTES:
30 //
31 //   * This file is a duplicate of Coin's lists/SbList.h file, and any
32 //   important fixes/improvements here should be migrated.
33 //
34 //   * This file contains definitions which should only be used during
35 //   library build for now. It is not yet installed for use by the
36 //   application programmer.
37 
38 /**************************************************************************/
39 
40 #include <Inventor/SbBasic.h>
41 #include <assert.h>
42 #include <stddef.h> // NULL definition
43 
44 // We usually implement inline functions below the class definition,
45 // since we think that makes the file more readable. However, this is
46 // not done for this class, since Visual C++ is not too happy about
47 // having functions declared as inline for a template class.
48 // pederb, 2001-10-12
49 
50 template <class Type>
51 class SbGuiList {
52   // Older compilers aren't too happy about const declarations in the
53   // class definitions, so use the enum trick described by Scott
54   // Meyers in "Effective C++".
55   enum { DEFAULTSIZE = 4 };
56 
57 public:
58 
59   SbGuiList(const int sizehint = DEFAULTSIZE)
itembuffersize(DEFAULTSIZE)60     : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
61     if (sizehint > DEFAULTSIZE) this->grow(sizehint);
62   }
63 
SbGuiList(const SbGuiList<Type> & l)64   SbGuiList(const SbGuiList<Type> & l)
65     : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
66     this->copy(l);
67   }
68 
~SbGuiList()69   ~SbGuiList() {
70     if (this->itembuffer != builtinbuffer) delete[] this->itembuffer;
71   }
72 
copy(const SbGuiList<Type> & l)73   void copy(const SbGuiList<Type> & l) {
74     if (this == &l) return;
75     const int n = l.numitems;
76     this->expand(n);
77     for (int i = 0; i < n; i++) this->itembuffer[i] = l.itembuffer[i];
78   }
79 
80   SbGuiList <Type> & operator=(const SbGuiList<Type> & l) {
81     this->copy(l);
82     return *this;
83   }
84 
fit(void)85   void fit(void) {
86     const int items = this->numitems;
87 
88     if (items < this->itembuffersize) {
89       Type * newitembuffer = this->builtinbuffer;
90       if (items > DEFAULTSIZE) newitembuffer = new Type[items];
91 
92       if (newitembuffer != this->itembuffer) {
93         for (int i = 0; i < items; i++) newitembuffer[i] = this->itembuffer[i];
94       }
95 
96       if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
97       this->itembuffer = newitembuffer;
98       this->itembuffersize = items > DEFAULTSIZE ? items : DEFAULTSIZE;
99     }
100   }
101 
append(const Type item)102   void append(const Type item) {
103     if (this->numitems == this->itembuffersize) this->grow();
104     this->itembuffer[this->numitems++] = item;
105   }
106 
find(const Type item)107   int find(const Type item) const {
108     for (int i = 0; i < this->numitems; i++)
109       if (this->itembuffer[i] == item) return i;
110     return -1;
111   }
112 
insert(const Type item,const int insertbefore)113   void insert(const Type item, const int insertbefore) {
114     assert(insertbefore >= 0 && insertbefore <= this->numitems);
115     if (this->numitems == this->itembuffersize) this->grow();
116 
117     for (int i = this->numitems; i > insertbefore; i--)
118       this->itembuffer[i] = this->itembuffer[i-1];
119     this->itembuffer[insertbefore] = item;
120     this->numitems++;
121   }
122 
removeItem(const Type item)123   void removeItem(const Type item) {
124     int idx = this->find(item);
125     assert(idx != -1);
126     this->remove(idx);
127   }
128 
remove(const int index)129   void remove(const int index) {
130     assert(index >= 0 && index < this->numitems);
131     this->numitems--;
132     for (int i = index; i < this->numitems; i++)
133       this->itembuffer[i] = this->itembuffer[i + 1];
134   }
135 
removeFast(const int index)136   void removeFast(const int index) {
137     assert(index >= 0 && index < this->numitems);
138     this->itembuffer[index] = this->itembuffer[--this->numitems];
139   }
140 
getLength(void)141   int getLength(void) const {
142     return this->numitems;
143   }
144 
145   void truncate(const int length, const int fit = 0) {
146     assert(length <= this->numitems);
147     this->numitems = length;
148     if (fit) this->fit();
149   }
150 
push(const Type item)151   void push(const Type item) {
152     this->append(item);
153   }
154 
pop(void)155   Type pop(void) {
156     assert(this->numitems > 0);
157     return this->itembuffer[--this->numitems];
158   }
159 
160   const Type * getArrayPtr(const int start = 0) const {
161     return &this->itembuffer[start];
162   }
163 
164   Type operator[](const int index) const {
165     assert(index >= 0 && index < this->numitems);
166     return this->itembuffer[index];
167   }
168 
169   Type & operator[](const int index) {
170     assert(index >= 0 && index < this->numitems);
171     return this->itembuffer[index];
172   }
173 
174   int operator==(const SbGuiList<Type> & l) const {
175     if (this == &l) return TRUE;
176     if (this->numitems != l.numitems) return FALSE;
177     for (int i = 0; i < this->numitems; i++)
178       if (this->itembuffer[i] != l.itembuffer[i]) return FALSE;
179     return TRUE;
180   }
181 
182   int operator!=(const SbGuiList<Type> & l) const {
183     return !(*this == l);
184   }
185 
186 protected:
187 
expand(const int size)188   void expand(const int size) {
189     this->grow(size);
190     this->numitems = size;
191   }
192 
getArraySize(void)193   int getArraySize(void) const {
194     return this->itembuffersize;
195   }
196 
197 private:
198   void grow(const int size = -1) {
199     // Default behavior is to double array size.
200     if (size == -1) this->itembuffersize <<= 1;
201     else if (size <= this->itembuffersize) return;
202     else { this->itembuffersize = size; }
203 
204     Type * newbuffer = new Type[this->itembuffersize];
205     const int n = this->numitems;
206     for (int i = 0; i < n; i++) newbuffer[i] = this->itembuffer[i];
207     if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
208     this->itembuffer = newbuffer;
209   }
210 
211   int itembuffersize;
212   int numitems;
213   Type * itembuffer;
214   Type builtinbuffer[DEFAULTSIZE];
215 };
216 
217 #endif // !SOGUI_SBGUILIST_H
218