1 #ifndef COIN_SOSUBFIELD_H
2 #define COIN_SOSUBFIELD_H
3 
4 /**************************************************************************\
5  * Copyright (c) Kongsberg Oil & Gas Technologies AS
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * Neither the name of the copyright holder nor the names of its
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 \**************************************************************************/
35 
36 #include <Inventor/SbBasic.h> // for SO__QUOTE() definition
37 #include <Inventor/SbName.h> // SoType::createType() needs to know SbName.
38 #include <Inventor/C/tidbits.h>
39 #include <cassert>
40 
41 #ifndef COIN_INTERNAL
42 // Added to be Inventor compliant.
43 #include <Inventor/fields/SoField.h>
44 #include <Inventor/SoInput.h>
45 #include <Inventor/SoOutput.h>
46 #endif // !COIN_INTERNAL
47 
48 /**************************************************************************
49  *
50  * Header macros for single-value fields.
51  *
52  **************************************************************************/
53 
54 #define SO_SFIELD_CONSTRUCTOR_HEADER(_class_) \
55 public: \
56   _class_(void); \
57   virtual ~_class_()
58 
59 
60 #define SO_SFIELD_REQUIRED_HEADER(_class_) \
61 private: \
62   static SoType classTypeId; \
63   static void atexit_cleanup(void) { SoType::removeType(_class_::classTypeId.getName()); _class_::classTypeId STATIC_SOTYPE_INIT; } \
64 public: \
65   static void * createInstance(void); \
66   static SoType getClassTypeId(void); \
67   virtual SoType getTypeId(void) const; \
68  \
69   virtual void copyFrom(const SoField & field); \
70   const _class_ & operator=(const _class_ & field); \
71   virtual SbBool isSame(const SoField & field) const
72 
73 
74 #define PRIVATE_SFIELD_IO_HEADER() \
75 private: \
76   virtual SbBool readValue(SoInput * in); \
77   virtual void writeValue(SoOutput * out) const
78 
79 
80 #define SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
81   PRIVATE_SFIELD_IO_HEADER(); \
82 protected: \
83   _valtype_ value; \
84  \
85 public: \
86   _valref_ getValue(void) const { this->evaluate(); return this->value; } \
87   void setValue(_valref_ newvalue); \
88   _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; } \
89  \
90   int operator==(const _class_ & field) const; \
91   int operator!=(const _class_ & field) const { return ! operator==(field); }
92 
93 
94 // FIXME: is really the operator=() definition below necessary?
95 // 19991226 mortene.
96 #define SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
97   PRIVATE_SFIELD_IO_HEADER(); \
98 public: \
99   _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; }
100 
101 
102 
103 #define SO_SFIELD_HEADER(_class_, _valtype_, _valref_) \
104   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
105   SO_SFIELD_REQUIRED_HEADER(_class_); \
106   SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
107 
108 
109 #define SO_SFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
110   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
111   SO_SFIELD_REQUIRED_HEADER(_class_); \
112   SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
113 
114 
115 
116 /**************************************************************************
117  *
118  * Source macros for single-value fields.
119  *
120  **************************************************************************/
121 
122 #define PRIVATE_FIELD_INIT_CLASS(_class_, _classname_, _parent_, _createfunc_) \
123   do { \
124     /* Make sure superclass get initialized before subclass. */ \
125     assert(_parent_::getClassTypeId() != SoType::badType()); \
126     /* Make sure we only initialize once. */ \
127     assert(_class_::classTypeId == SoType::badType()); \
128     _class_::classTypeId = \
129       SoType::createType(_parent_::getClassTypeId(), _classname_, _createfunc_); \
130     cc_coin_atexit_static_internal \
131       ( \
132        _class_::atexit_cleanup \
133        ); \
134   } WHILE_0
135 
136 
137 
138 #define SO_SFIELD_INIT_CLASS(_class_, _parent_) \
139   do { \
140     const char * classname = SO__QUOTE(_class_); \
141     PRIVATE_FIELD_INIT_CLASS(_class_, classname, _parent_, &_class_::createInstance); \
142   } WHILE_0
143 
144 #define SO_SFIELD_CONSTRUCTOR_SOURCE(_class_) \
145 _class_::_class_(void) { assert(_class_::classTypeId != SoType::badType()); } \
146 _class_::~_class_() { }
147 
148 
149 
150 #define SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
151 void \
152 _class_::setValue(_valref_ valuearg) { \
153   this->value = valuearg; \
154   this->valueChanged(); \
155 } \
156  \
157 SbBool \
158 _class_::operator==(const _class_ & field) const \
159 { \
160   return (this->getValue() == field.getValue()); \
161 }
162 
163 
164 #define PRIVATE_TYPEID_SOURCE(_class_) \
165 SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
166 SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
167 void * _class_::createInstance(void) { return new _class_; } \
168 SoType _class_::classTypeId STATIC_SOTYPE_INIT
169 
170 
171 #define PRIVATE_EQUALITY_SOURCE(_class_) \
172 void \
173 _class_::copyFrom(const SoField & field) \
174 { \
175   this->operator=(static_cast<const _class_ &>(field)); \
176 } \
177  \
178 SbBool \
179 _class_::isSame(const SoField & field) const \
180 { \
181   if (field.getTypeId() != this->getTypeId()) return FALSE; \
182   return this->operator==(static_cast<const _class_ &>(field)); \
183 }
184 
185 
186 
187 #define SO_SFIELD_REQUIRED_SOURCE(_class_) \
188 PRIVATE_TYPEID_SOURCE(_class_); \
189 PRIVATE_EQUALITY_SOURCE(_class_); \
190  \
191 const _class_ & \
192 _class_::operator=(const _class_ & field) \
193 { \
194   this->setValue(field.getValue()); \
195   return *this; \
196 }
197 
198 
199 
200 #define SO_SFIELD_SOURCE(_class_, _valtype_, _valref_) \
201   SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
202   SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_); \
203   SO_SFIELD_REQUIRED_SOURCE(_class_)
204 
205 
206 
207 #define SO_SFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
208   SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
209   SO_SFIELD_REQUIRED_SOURCE(_class_)
210 
211 
212 /**************************************************************************
213  *
214  * Header macros for multiple-value fields.
215  *
216  **************************************************************************/
217 
218 #define PRIVATE_MFIELD_IO_HEADER() \
219 private: \
220   virtual SbBool read1Value(SoInput * in, int idx); \
221   virtual void write1Value(SoOutput * out, int idx) const
222 
223 
224 
225 #define SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
226   PRIVATE_MFIELD_IO_HEADER(); \
227 protected: \
228   virtual void deleteAllValues(void); \
229   virtual void copyValue(int to, int from); \
230   virtual int fieldSizeof(void) const; \
231   virtual void * valuesPtr(void); \
232   virtual void setValuesPtr(void * ptr); \
233   virtual void allocValues(int num); \
234  \
235   _valtype_ * values; \
236 public: \
237   _valref_ operator[](const int idx) const \
238     { this->evaluate(); return this->values[idx]; } \
239 /*! \
240   Returns a pointer to the values array. \
241 */ \
242   const _valtype_ * getValues(const int start) const \
243     { this->evaluate(); return const_cast<const _valtype_ *>(this->values + start); } \
244   int find(_valref_ value, SbBool addifnotfound = FALSE); \
245   void setValues(const int start, const int num, const _valtype_ * newvals); \
246   void set1Value(const int idx, _valref_ value); \
247   void setValue(_valref_ value); \
248   _valref_ operator=(_valref_ val) { this->setValue(val); return val; } \
249   SbBool operator==(const _class_ & field) const; \
250   SbBool operator!=(const _class_ & field) const { return !operator==(field); } \
251   _valtype_ * startEditing(void) { this->evaluate(); return this->values; } \
252   void finishEditing(void) { this->valueChanged(); }
253 
254 #define SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
255   PRIVATE_MFIELD_IO_HEADER(); \
256 public: \
257   _valref_ operator=(_valref_ val) { this->setValue(val); return val; }
258 
259 
260 
261 #define SO_MFIELD_HEADER(_class_, _valtype_, _valref_) \
262   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
263   SO_SFIELD_REQUIRED_HEADER(_class_); \
264   SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
265 
266 
267 
268 #define SO_MFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
269   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
270   SO_SFIELD_REQUIRED_HEADER(_class_); \
271   SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
272 
273 #define SO_MFIELD_SETVALUESPOINTER_HEADER(_valtype_) \
274   void setValuesPointer(const int num, const _valtype_ * userdata); \
275   void setValuesPointer(const int num, _valtype_ * userdata)
276 
277 
278 /**************************************************************************
279  *
280  * Source macros for multiple-value fields.
281  *
282  **************************************************************************/
283 
284 
285 #define SO_MFIELD_INIT_CLASS(_class_, _parent_) \
286   SO_SFIELD_INIT_CLASS(_class_, _parent_)
287 
288 
289 
290 #define SO_MFIELD_CONSTRUCTOR_SOURCE(_class_) \
291 _class_::_class_(void) \
292 { \
293   assert(_class_::classTypeId != SoType::badType()); \
294   this->values = NULL; \
295 } \
296  \
297 _class_::~_class_(void) \
298 { \
299   this->enableNotify(FALSE); /* Avoid notifying destructed containers. */ \
300   this->deleteAllValues(); \
301 }
302 
303 
304 
305 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) \
306 _class_::_class_(void) { } \
307 _class_::~_class_(void) { }
308 
309 
310 
311 #define SO_MFIELD_REQUIRED_SOURCE(_class_) \
312 PRIVATE_TYPEID_SOURCE(_class_); \
313 PRIVATE_EQUALITY_SOURCE(_class_); \
314 const _class_ & \
315 _class_::operator=(const _class_ & field) \
316 { \
317   /* The allocValues() call is needed, as setValues() doesn't */ \
318   /* necessarily make the field's getNum() size become the same */ \
319   /* as the second argument (only if it expands on the old size). */ \
320   this->allocValues(field.getNum()); \
321   \
322   this->setValues(0, field.getNum(), field.getValues(0)); \
323   return *this; \
324 }
325 
326 
327 
328 #define SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
329 int \
330 _class_::fieldSizeof(void) const \
331 { \
332   return sizeof(_valtype_); \
333 } \
334  \
335 void * \
336 _class_::valuesPtr(void) \
337 { \
338   return static_cast<void *>(this->values); \
339 } \
340  \
341 void \
342 _class_::setValuesPtr(void * ptr) \
343 { \
344   this->values = static_cast<_valtype_ *>(ptr); \
345 } \
346  \
347 int \
348 _class_::find(_valref_ value, SbBool addifnotfound) \
349 { \
350   evaluate(); \
351   for (int i=0; i < this->num; i++) if (this->values[i] == value) return i; \
352  \
353   if (addifnotfound) this->set1Value(this->num, value); \
354   return -1; \
355 } \
356  \
357 void \
358 _class_::setValues(const int start, const int numarg, const _valtype_ * newvals) \
359 { \
360   if (start+numarg > this->maxNum) this->allocValues(start+numarg); \
361   else if (start+numarg > this->num) this->num = start+numarg; \
362  \
363   for (int i=0; i < numarg; i++) \
364     this->values[i+start] = static_cast<const _valtype_>(newvals[i]); \
365   this->setChangedIndices(start, numarg); \
366   this->valueChanged(); \
367   this->setChangedIndices(); \
368 } \
369  \
370 void \
371 _class_::set1Value(const int idx, _valref_ value) \
372 { \
373   if (idx+1 > this->maxNum) this->allocValues(idx+1); \
374   else if (idx+1 > this->num) this->num = idx+1; \
375   this->values[idx] = value; \
376   this->setChangedIndex(idx); \
377   this->valueChanged(); \
378   this->setChangedIndices(); \
379 } \
380  \
381 void \
382 _class_::setValue(_valref_ value) \
383 { \
384   this->allocValues(1); \
385   this->values[0] = value; \
386   this->setChangedIndex(0); \
387   this->valueChanged(); \
388   this->setChangedIndices(); \
389 } \
390  \
391 SbBool \
392 _class_::operator==(const _class_ & field) const \
393 { \
394   if (this == &field) return TRUE; \
395   if (this->getNum() != field.getNum()) return FALSE; \
396  \
397   const _valtype_ * const lhs = this->getValues(0); \
398   const _valtype_ * const rhs = field.getValues(0); \
399   for (int i = 0; i < this->num; i++) if (lhs[i] != rhs[i]) return FALSE; \
400   return TRUE; \
401 } \
402  \
403 /*! \COININTERNAL */ \
404 void \
405 _class_::deleteAllValues(void) \
406 { \
407   this->setNum(0); \
408 } \
409  \
410 /*! This method is used for moving values around internally within a multivalue field. It needs to be overridden in each field so it automatically takes care of running copy contructors where necessary. */ \
411 void \
412 _class_::copyValue(int to, int from) \
413 { \
414   this->values[to] = this->values[from]; \
415 }
416 
417 
418 #define SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_) \
419 void \
420 _class_::allocValues(int newnum) \
421 { \
422   /* Important notice: the "malloc-version" of this method is found */ \
423   /* in SoMField.cpp. If you make modifications here, do check whether */ \
424   /* or not they should be matched with modifications in that method */ \
425   /* aswell. */ \
426  \
427   /* these must be declared here as a gcc 4.0.0 bug workaround */ \
428   int i; \
429   int oldmaxnum; \
430   _valtype_ * newblock; \
431   assert(newnum >= 0); \
432  \
433   this->setChangedIndices(); \
434   if (newnum == 0) { \
435     if (!this->userDataIsUsed) delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
436     this->setValuesPtr(NULL); \
437     this->maxNum = 0; \
438     this->userDataIsUsed = FALSE; \
439   } \
440   else if (newnum > this->maxNum || newnum < this->num) { \
441     if (this->valuesPtr()) { \
442  \
443       /* Allocation strategy is to repeatedly double the size of the */ \
444       /* allocated block until it will at least match the requested size. */ \
445       /* (Unless the requested size is less than what we've got, */ \
446       /* then we'll repeatedly halve the allocation size.) */ \
447       /* */ \
448       /* I think this will handle both cases quite gracefully: */ \
449       /* 1) newnum > this->maxNum, 2) newnum < num */ \
450       oldmaxnum = this->maxNum; \
451       while (newnum > this->maxNum) this->maxNum *= 2; \
452       while ((this->maxNum / 2) >= newnum) this->maxNum /= 2; \
453  \
454       if (oldmaxnum != this->maxNum) { \
455         newblock = new _valtype_[this->maxNum]; \
456  \
457         for (i=0; i < SbMin(this->num, newnum); i++) \
458           newblock[i] = this->values[i]; \
459  \
460         delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
461         this->setValuesPtr(newblock); \
462         this->userDataIsUsed = FALSE; \
463       } \
464     } \
465     else { \
466       this->setValuesPtr(new _valtype_[newnum]); \
467       this->userDataIsUsed = FALSE; \
468       this->maxNum = newnum; \
469     } \
470   } \
471  \
472   this->num = newnum; \
473 }
474 
475 
476 
477 #define SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_) \
478 void \
479 _class_::allocValues(int number) \
480 { \
481   SoMField::allocValues(number); \
482 }
483 
484 
485 
486 #define SO_MFIELD_SOURCE_MALLOC(_class_, _valtype_, _valref_) \
487   SO_MFIELD_REQUIRED_SOURCE(_class_); \
488   SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
489   SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_); \
490   SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
491 
492 
493 
494 #define SO_MFIELD_SOURCE(_class_, _valtype_, _valref_) \
495   SO_MFIELD_REQUIRED_SOURCE(_class_); \
496   SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
497   SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_); \
498   SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
499 
500 
501 #define SO_MFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
502   SO_MFIELD_REQUIRED_SOURCE(_class_); \
503   SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_)
504 
505 #define SO_MFIELD_SETVALUESPOINTER_SOURCE(_class_, _valtype_, _usertype_) \
506 void \
507 _class_::setValuesPointer(const int numarg, _usertype_ * userdata) \
508 { \
509   this->makeRoom(0); \
510   if (numarg > 0 && userdata) { \
511     this->values = reinterpret_cast<_valtype_*>(userdata); /* reinterpret_cast is needed for certain special uses of this function, such as SoMFColor */ \
512     this->userDataIsUsed = TRUE; \
513     this->num = this->maxNum = numarg; \
514     this->valueChanged(); \
515   } \
516 } \
517 void \
518 _class_::setValuesPointer(const int numarg, const _usertype_ * userdata) \
519 { \
520   this->setValuesPointer(numarg, const_cast<_usertype_*>(userdata)); \
521 }
522 
523 #endif // !COIN_SOSUBFIELD_H
524