1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoBaseList SoBaseList.h Inventor/lists/SoBaseList.h
35 \brief The SoBaseList class is a container for pointers to SoBase derived objects.
36
37 \ingroup general
38
39 The additional capability of the SoBaseList class over its parent
40 class, SbPList, is to automatically handle referencing and
41 dereferencing of items as they are added or removed from the lists.
42 */
43
44 #include <Inventor/lists/SoBaseList.h>
45 #include <Inventor/misc/SoBase.h>
46 #include <cassert>
47
48 // Convenience macro for casting array element from void * to SoBase *.
49 #define GET_BASEPTR(idx) ((SoBase *)SbPList::get(idx))
50
51
52 /*!
53 Default constructor.
54 */
SoBaseList(void)55 SoBaseList::SoBaseList(void)
56 : SbPList(), referencing(TRUE)
57 {
58 }
59
60 /*!
61 Constructor with a hint about the maximum number of pointers in the
62 list.
63
64 \sa SbPList::SbPList(const int)
65 */
SoBaseList(const int size)66 SoBaseList::SoBaseList(const int size)
67 : SbPList(size), referencing(TRUE)
68 {
69 }
70
71 /*!
72 Copy constructor.
73
74 Shallow copy the items of \a l into this list, adding to the item
75 reference counts if the reference flag of \a l is \c TRUE.
76
77 \sa SbPList::SbPList(const SbPList &)
78 */
SoBaseList(const SoBaseList & l)79 SoBaseList::SoBaseList(const SoBaseList & l)
80 : SbPList(l) // copies list items "raw"
81 {
82 this->referencing = l.referencing;
83 if (this->referencing) {
84 const int n = this->getLength();
85 for (int i = 0; i < n; i++) GET_BASEPTR(i)->ref();
86 }
87 }
88
89 /*!
90 Destructor. Dereferences items before freeing resources.
91 */
~SoBaseList()92 SoBaseList::~SoBaseList()
93 {
94 this->truncate(0); // truncate() does unref-ing
95 }
96
97 /*!
98 Append \a ptr to list, adding to the reference count of the object
99 (unless addReferences() has been set to \c FALSE).
100
101 \sa SbPList::append()
102 */
103 void
append(SoBase * ptr)104 SoBaseList::append(SoBase * ptr)
105 {
106 if (this->referencing && ptr) ptr->ref();
107 SbPList::append((void *)ptr);
108 }
109
110 /*!
111 Insert \a ptr in the list at position \a addbefore, adding to the
112 reference count of the object (unless addReferences() has been set
113 to \c FALSE).
114
115 \sa SbPList::insert()
116 */
117 void
insert(SoBase * ptr,const int addbefore)118 SoBaseList::insert(SoBase * ptr, const int addbefore)
119 {
120 if (this->referencing && ptr) ptr->ref();
121 SbPList::insert((void *)ptr, addbefore);
122 }
123
124 /*!
125 Removes item at \a index from the list, dereferencing the object
126 (unless addReferences() has been set to \c FALSE).
127
128 \sa SbPList::remove()
129 */
130 void
remove(const int index)131 SoBaseList::remove(const int index)
132 {
133 assert(index >= 0 && index < this->getLength());
134 if (this->referencing && GET_BASEPTR(index) != NULL)
135 GET_BASEPTR(index)->unref();
136 SbPList::remove(index);
137 }
138
139 /*!
140 Removes \a item from the list, dereferencing the object (unless
141 addReferences() has been set to \c FALSE).
142
143 \sa SbPList::removeItem()
144 */
145 void
removeItem(SoBase * item)146 SoBaseList::removeItem(SoBase * item)
147 {
148 // We need to override the removeItem() function from our SbPList
149 // superclass, or invocations of it will not cause a decrease of the
150 // reference count.
151
152 // Just forward call to remove(), which takes care of the
153 // dereferencing.
154 this->remove(this->find(item));
155 }
156
157 /*!
158 Makes the list contain only the \a length first items, removing all
159 items from index \a length and onwards to the end of the
160 list. Dereferences the objects to be removed (unless addReferences()
161 has been set to \c FALSE).
162
163 \sa SbPList::truncate()
164 */
165 void
truncate(const int length)166 SoBaseList::truncate(const int length)
167 {
168 if (this->referencing) {
169 const int n = this->getLength();
170 for (int i = length; i < n; i++)
171 if (GET_BASEPTR(i) != NULL) GET_BASEPTR(i)->unref();
172 }
173 SbPList::truncate(length);
174 }
175
176 /*!
177 Shallow copy of the item pointers of \a l list into this one, first
178 removing all items in this list.
179 */
180 void
copy(const SoBaseList & l)181 SoBaseList::copy(const SoBaseList & l)
182 {
183 if (this == &l) return;
184
185 this->truncate(0);
186
187 this->referencing = l.referencing;
188 const int n = l.getLength();
189 for (int i = 0; i < n; i++) this->append(l[i]); // handles ref'ing
190 }
191
192 /*!
193 Shallow copy of the SoBase pointers from \a l into this one,
194 returning a pointer to ourself.
195
196 \sa copy()
197 */
198 SoBaseList &
operator =(const SoBaseList & l)199 SoBaseList::operator=(const SoBaseList & l)
200 {
201 this->copy(l);
202 return *this;
203 }
204
205 /*!
206 Returns element at \a idx.
207
208 Will automatically expand the size of the internal array if \a idx
209 is outside the current bounds of the list. The values of any
210 additional pointers are then set to \c NULL.
211 */
212 SoBase *
operator [](const int idx) const213 SoBaseList::operator[](const int idx) const
214 {
215 // Overridden from superclass to cast from the \c void pointer
216 // actually stored.
217
218 return (SoBase *)SbPList::operator[](idx);
219 }
220
221 /*!
222 Decide whether or not the SoBase items should be automatically
223 referenced and dereferenced as they are added and removed from the
224 list.
225
226 Default setting is to do referencing.
227 */
228 void
addReferences(const SbBool flag)229 SoBaseList::addReferences(const SbBool flag)
230 {
231 #if 0 // OBSOLETED: don't do this, it looks like it could give the
232 // user some nasty surprises. 20000228 mortene.
233
234 // this method should probably never be called when there are items in
235 // the list, but I think the code below should handle that case also.
236 // If refing changes from on to off, all items are unref'ed, since
237 // they were ref'ed when inserted. If state changes from off to on, all
238 // items are ref'ed, since they will be unref'ed when removed from list.
239
240 if (flag == this->referencing) return; // no change
241
242 const int n = this->getLength();
243 for (int i = 0; i < n; i++) {
244 SoBase * item = GET_BASEPTR(i);
245 if (item) {
246 if (flag) item->ref();
247 else item->unref();
248 }
249 }
250
251 #else
252
253 assert(this->getLength() == 0);
254
255 #endif
256
257 this->referencing = flag;
258 }
259
260 /*!
261 Return whether the SoBase instances are automatically referenced
262 and dereferenced when they are added and removed from the list.
263
264 \COIN_FUNCTION_EXTENSION
265
266 \sa addReferences()
267 \since Coin 2.0
268 */
269 SbBool
isReferencing(void) const270 SoBaseList::isReferencing(void) const
271 {
272 return this->referencing;
273 }
274
275 /*!
276 Index operator to set element at \a i. Does \e not expand array
277 bounds if \a i is outside the list.
278 */
279 void
set(const int i,SoBase * const ptr)280 SoBaseList::set(const int i, SoBase * const ptr)
281 {
282 // Overridden from parent class to provide referencing on the SoBase
283 // object.
284
285 if (this->referencing) {
286 // Note: it's important to ref() before we unref(), in case the
287 // value of ptr is equal to the old value (otherwise we could
288 // unref() it to zero, which causes premature destruction).
289 if (ptr) ptr->ref();
290 if (GET_BASEPTR(i)) GET_BASEPTR(i)->unref();
291 }
292 SbPList::set(i, (void *)ptr);
293 }
294
295
296 #undef GET_BASEPTR
297