Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
SoSubField.h
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  \
166  \
171 SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
172  \
173  \
177 SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
178  \
182 void * _class_::createInstance(void) { return new _class_; } \
183 SoType _class_::classTypeId STATIC_SOTYPE_INIT
184 
185 
186 #define PRIVATE_EQUALITY_SOURCE(_class_) \
187 void \
188 _class_::copyFrom(const SoField & field) \
189 { \
190  this->operator=(static_cast<const _class_ &>(field)); \
191 } \
192  \
193 SbBool \
194 _class_::isSame(const SoField & field) const \
195 { \
196  if (field.getTypeId() != this->getTypeId()) return FALSE; \
197  return this->operator==(static_cast<const _class_ &>(field)); \
198 }
199 
200 
201 
202 #define SO_SFIELD_REQUIRED_SOURCE(_class_) \
203 PRIVATE_TYPEID_SOURCE(_class_); \
204 PRIVATE_EQUALITY_SOURCE(_class_); \
205  \
206 const _class_ & \
207 _class_::operator=(const _class_ & field) \
208 { \
209  this->setValue(field.getValue()); \
210  return *this; \
211 }
212 
213 
214 
215 #define SO_SFIELD_SOURCE(_class_, _valtype_, _valref_) \
216  SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
217  SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_); \
218  SO_SFIELD_REQUIRED_SOURCE(_class_)
219 
220 
221 
222 #define SO_SFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
223  SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
224  SO_SFIELD_REQUIRED_SOURCE(_class_)
225 
226 
227 /**************************************************************************
228  *
229  * Header macros for multiple-value fields.
230  *
231  **************************************************************************/
232 
233 #define PRIVATE_MFIELD_IO_HEADER() \
234 private: \
235  virtual SbBool read1Value(SoInput * in, int idx); \
236  virtual void write1Value(SoOutput * out, int idx) const
237 
238 
239 
240 #define SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
241  PRIVATE_MFIELD_IO_HEADER(); \
242 protected: \
243  virtual void deleteAllValues(void); \
244  virtual void copyValue(int to, int from); \
245  virtual int fieldSizeof(void) const; \
246  virtual void * valuesPtr(void); \
247  virtual void setValuesPtr(void * ptr); \
248  virtual void allocValues(int num); \
249  \
250  _valtype_ * values; \
251 public: \
252  _valref_ operator[](const int idx) const \
253  { this->evaluate(); return this->values[idx]; } \
254  \
257  const _valtype_ * getValues(const int start) const \
258  { this->evaluate(); return const_cast<const _valtype_ *>(this->values + start); } \
259  int find(_valref_ value, SbBool addifnotfound = FALSE); \
260  void setValues(const int start, const int num, const _valtype_ * newvals); \
261  void set1Value(const int idx, _valref_ value); \
262  void setValue(_valref_ value); \
263  _valref_ operator=(_valref_ val) { this->setValue(val); return val; } \
264  SbBool operator==(const _class_ & field) const; \
265  SbBool operator!=(const _class_ & field) const { return !operator==(field); } \
266  _valtype_ * startEditing(void) { this->evaluate(); return this->values; } \
267  void finishEditing(void) { this->valueChanged(); }
268 
269 #define SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
270  PRIVATE_MFIELD_IO_HEADER(); \
271 public: \
272  _valref_ operator=(_valref_ val) { this->setValue(val); return val; }
273 
274 
275 
276 #define SO_MFIELD_HEADER(_class_, _valtype_, _valref_) \
277  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
278  SO_SFIELD_REQUIRED_HEADER(_class_); \
279  SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
280 
281 
282 
283 #define SO_MFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
284  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
285  SO_SFIELD_REQUIRED_HEADER(_class_); \
286  SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
287 
288 #define SO_MFIELD_SETVALUESPOINTER_HEADER(_valtype_) \
289  void setValuesPointer(const int num, const _valtype_ * userdata); \
290  void setValuesPointer(const int num, _valtype_ * userdata)
291 
292 
293 /**************************************************************************
294  *
295  * Source macros for multiple-value fields.
296  *
297  **************************************************************************/
298 
299 
300 #define SO_MFIELD_INIT_CLASS(_class_, _parent_) \
301  SO_SFIELD_INIT_CLASS(_class_, _parent_)
302 
303 
304 
305 #define SO_MFIELD_CONSTRUCTOR_SOURCE(_class_) \
306 _class_::_class_(void) \
307 { \
308  assert(_class_::classTypeId != SoType::badType()); \
309  this->values = NULL; \
310 } \
311  \
312 _class_::~_class_(void) \
313 { \
314  this->enableNotify(FALSE); /* Avoid notifying destructed containers. */ \
315  this->deleteAllValues(); \
316 }
317 
318 
319 
320 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) \
321 _class_::_class_(void) { } \
322 _class_::~_class_(void) { }
323 
324 
325 
326 #define SO_MFIELD_REQUIRED_SOURCE(_class_) \
327 PRIVATE_TYPEID_SOURCE(_class_); \
328 PRIVATE_EQUALITY_SOURCE(_class_); \
329 const _class_ & \
330 _class_::operator=(const _class_ & field) \
331 { \
332  /* The allocValues() call is needed, as setValues() doesn't */ \
333  /* necessarily make the field's getNum() size become the same */ \
334  /* as the second argument (only if it expands on the old size). */ \
335  this->allocValues(field.getNum()); \
336  \
337  this->setValues(0, field.getNum(), field.getValues(0)); \
338  return *this; \
339 }
340 
341 
342 
343 #define SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
344 int \
345 _class_::fieldSizeof(void) const \
346 { \
347  return sizeof(_valtype_); \
348 } \
349  \
350 void * \
351 _class_::valuesPtr(void) \
352 { \
353  return static_cast<void *>(this->values); \
354 } \
355  \
356 void \
357 _class_::setValuesPtr(void * ptr) \
358 { \
359  this->values = static_cast<_valtype_ *>(ptr); \
360 } \
361  \
362 int \
363 _class_::find(_valref_ value, SbBool addifnotfound) \
364 { \
365  evaluate(); \
366  for (int i=0; i < this->num; i++) if (this->values[i] == value) return i; \
367  \
368  if (addifnotfound) this->set1Value(this->num, value); \
369  return -1; \
370 } \
371  \
372 void \
373 _class_::setValues(const int start, const int numarg, const _valtype_ * newvals) \
374 { \
375  if (start+numarg > this->maxNum) this->allocValues(start+numarg); \
376  else if (start+numarg > this->num) this->num = start+numarg; \
377  \
378  for (int i=0; i < numarg; i++) \
379  this->values[i+start] = static_cast<const _valtype_>(newvals[i]); \
380  this->setChangedIndices(start, numarg); \
381  this->valueChanged(); \
382  this->setChangedIndices(); \
383 } \
384  \
385 void \
386 _class_::set1Value(const int idx, _valref_ value) \
387 { \
388  if (idx+1 > this->maxNum) this->allocValues(idx+1); \
389  else if (idx+1 > this->num) this->num = idx+1; \
390  this->values[idx] = value; \
391  this->setChangedIndex(idx); \
392  this->valueChanged(); \
393  this->setChangedIndices(); \
394 } \
395  \
396 void \
397 _class_::setValue(_valref_ value) \
398 { \
399  this->allocValues(1); \
400  this->values[0] = value; \
401  this->setChangedIndex(0); \
402  this->valueChanged(); \
403  this->setChangedIndices(); \
404 } \
405  \
406 SbBool \
407 _class_::operator==(const _class_ & field) const \
408 { \
409  if (this == &field) return TRUE; \
410  if (this->getNum() != field.getNum()) return FALSE; \
411  \
412  const _valtype_ * const lhs = this->getValues(0); \
413  const _valtype_ * const rhs = field.getValues(0); \
414  for (int i = 0; i < this->num; i++) if (lhs[i] != rhs[i]) return FALSE; \
415  return TRUE; \
416 } \
417  \
418  \
419 void \
420 _class_::deleteAllValues(void) \
421 { \
422  this->setNum(0); \
423 } \
424  \
425  \
426 void \
427 _class_::copyValue(int to, int from) \
428 { \
429  this->values[to] = this->values[from]; \
430 }
431 
432 
433 #define SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_) \
434 void \
435 _class_::allocValues(int newnum) \
436 { \
437  /* Important notice: the "malloc-version" of this method is found */ \
438  /* in SoMField.cpp. If you make modifications here, do check whether */ \
439  /* or not they should be matched with modifications in that method */ \
440  /* aswell. */ \
441  \
442  /* these must be declared here as a gcc 4.0.0 bug workaround */ \
443  int i; \
444  int oldmaxnum; \
445  _valtype_ * newblock; \
446  assert(newnum >= 0); \
447  \
448  this->setChangedIndices(); \
449  if (newnum == 0) { \
450  if (!this->userDataIsUsed) delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
451  this->setValuesPtr(NULL); \
452  this->maxNum = 0; \
453  this->userDataIsUsed = FALSE; \
454  } \
455  else if (newnum > this->maxNum || newnum < this->num) { \
456  if (this->valuesPtr()) { \
457  \
458  /* Allocation strategy is to repeatedly double the size of the */ \
459  /* allocated block until it will at least match the requested size. */ \
460  /* (Unless the requested size is less than what we've got, */ \
461  /* then we'll repeatedly halve the allocation size.) */ \
462  /* */ \
463  /* I think this will handle both cases quite gracefully: */ \
464  /* 1) newnum > this->maxNum, 2) newnum < num */ \
465  oldmaxnum = this->maxNum; \
466  while (newnum > this->maxNum) this->maxNum *= 2; \
467  while ((this->maxNum / 2) >= newnum) this->maxNum /= 2; \
468  \
469  if (oldmaxnum != this->maxNum) { \
470  newblock = new _valtype_[this->maxNum]; \
471  \
472  for (i=0; i < SbMin(this->num, newnum); i++) \
473  newblock[i] = this->values[i]; \
474  \
475  delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
476  this->setValuesPtr(newblock); \
477  this->userDataIsUsed = FALSE; \
478  } \
479  } \
480  else { \
481  this->setValuesPtr(new _valtype_[newnum]); \
482  this->userDataIsUsed = FALSE; \
483  this->maxNum = newnum; \
484  } \
485  } \
486  \
487  this->num = newnum; \
488 }
489 
490 
491 
492 #define SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_) \
493 void \
494 _class_::allocValues(int number) \
495 { \
496  SoMField::allocValues(number); \
497 }
498 
499 
500 
501 #define SO_MFIELD_SOURCE_MALLOC(_class_, _valtype_, _valref_) \
502  SO_MFIELD_REQUIRED_SOURCE(_class_); \
503  SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
504  SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_); \
505  SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
506 
507 
508 
509 #define SO_MFIELD_SOURCE(_class_, _valtype_, _valref_) \
510  SO_MFIELD_REQUIRED_SOURCE(_class_); \
511  SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
512  SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_); \
513  SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
514 
515 
516 #define SO_MFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
517  SO_MFIELD_REQUIRED_SOURCE(_class_); \
518  SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_)
519 
520 #define SO_MFIELD_SETVALUESPOINTER_SOURCE(_class_, _valtype_, _usertype_) \
521 void \
522 _class_::setValuesPointer(const int numarg, _usertype_ * userdata) \
523 { \
524  this->makeRoom(0); \
525  if (numarg > 0 && userdata) { \
526  this->values = reinterpret_cast<_valtype_*>(userdata); /* reinterpret_cast is needed for certain special uses of this function, such as SoMFColor */ \
527  this->userDataIsUsed = TRUE; \
528  this->num = this->maxNum = numarg; \
529  this->valueChanged(); \
530  } \
531 } \
532 void \
533 _class_::setValuesPointer(const int numarg, const _usertype_ * userdata) \
534 { \
535  this->setValuesPointer(numarg, const_cast<_usertype_*>(userdata)); \
536 }
537 
538 #endif // !COIN_SOSUBFIELD_H