Coin Logo http://www.sim.no/
http://www.coin3d.org/

SoSubField.h
1 #ifndef COIN_SOSUBFIELD_H
2 #define COIN_SOSUBFIELD_H
3 
4 /**************************************************************************\
5  *
6  * This file is part of the Coin 3D visualization library.
7  * Copyright (C) by Kongsberg Oil & Gas Technologies.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * ("GPL") version 2 as published by the Free Software Foundation.
12  * See the file LICENSE.GPL at the root directory of this source
13  * distribution for additional information about the GNU GPL.
14  *
15  * For using Coin with software that can not be combined with the GNU
16  * GPL, and for taking advantage of the additional benefits of our
17  * support services, please contact Kongsberg Oil & Gas Technologies
18  * about acquiring a Coin Professional Edition License.
19  *
20  * See http://www.coin3d.org/ for more information.
21  *
22  * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
23  * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
24  *
25 \**************************************************************************/
26 
27 #include <Inventor/SbBasic.h> // for SO__QUOTE() definition
28 #include <Inventor/SbName.h> // SoType::createType() needs to know SbName.
29 #include <Inventor/C/tidbits.h>
30 #include <assert.h>
31 
32 #ifndef COIN_INTERNAL
33 // Added to be Inventor compliant.
34 #include <Inventor/fields/SoField.h>
35 #include <Inventor/SoInput.h>
36 #include <Inventor/SoOutput.h>
37 #endif // !COIN_INTERNAL
38 
39 /**************************************************************************
40  *
41  * Header macros for single-value fields.
42  *
43  **************************************************************************/
44 
45 #define SO_SFIELD_CONSTRUCTOR_HEADER(_class_) \
46 public: \
47  _class_(void); \
48  virtual ~_class_()
49 
50 
51 #define SO_SFIELD_REQUIRED_HEADER(_class_) \
52 private: \
53  static SoType classTypeId; \
54  static void atexit_cleanup(void) { SoType::removeType(_class_::classTypeId.getName()); _class_::classTypeId STATIC_SOTYPE_INIT; } \
55 public: \
56  static void * createInstance(void); \
57  static SoType getClassTypeId(void); \
58  virtual SoType getTypeId(void) const; \
59  \
60  virtual void copyFrom(const SoField & field); \
61  const _class_ & operator=(const _class_ & field); \
62  virtual SbBool isSame(const SoField & field) const
63 
64 
65 #define PRIVATE_SFIELD_IO_HEADER() \
66 private: \
67  virtual SbBool readValue(SoInput * in); \
68  virtual void writeValue(SoOutput * out) const
69 
70 
71 #define SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
72  PRIVATE_SFIELD_IO_HEADER(); \
73 protected: \
74  _valtype_ value; \
75  \
76 public: \
77  _valref_ getValue(void) const { this->evaluate(); return this->value; } \
78  void setValue(_valref_ newvalue); \
79  _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; } \
80  \
81  int operator==(const _class_ & field) const; \
82  int operator!=(const _class_ & field) const { return ! operator==(field); }
83 
84 
85 // FIXME: is really the operator=() definition below necessary?
86 // 19991226 mortene.
87 #define SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
88  PRIVATE_SFIELD_IO_HEADER(); \
89 public: \
90  _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; }
91 
92 
93 
94 #define SO_SFIELD_HEADER(_class_, _valtype_, _valref_) \
95  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
96  SO_SFIELD_REQUIRED_HEADER(_class_); \
97  SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
98 
99 
100 #define SO_SFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
101  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
102  SO_SFIELD_REQUIRED_HEADER(_class_); \
103  SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
104 
105 
106 
107 /**************************************************************************
108  *
109  * Source macros for single-value fields.
110  *
111  **************************************************************************/
112 
113 #define PRIVATE_FIELD_INIT_CLASS(_class_, _classname_, _parent_, _createfunc_) \
114  do { \
115  /* Make sure superclass get initialized before subclass. */ \
116  assert(_parent_::getClassTypeId() != SoType::badType()); \
117  /* Make sure we only initialize once. */ \
118  assert(_class_::classTypeId == SoType::badType()); \
119  _class_::classTypeId = \
120  SoType::createType(_parent_::getClassTypeId(), _classname_, _createfunc_); \
121  cc_coin_atexit_static_internal \
122  ( \
123  _class_::atexit_cleanup \
124  ); \
125  } while (0)
126 
127 
128 
129 #define SO_SFIELD_INIT_CLASS(_class_, _parent_) \
130  do { \
131  const char * classname = SO__QUOTE(_class_); \
132  PRIVATE_FIELD_INIT_CLASS(_class_, classname, _parent_, &_class_::createInstance); \
133  } while (0)
134 
135 #define SO_SFIELD_CONSTRUCTOR_SOURCE(_class_) \
136 _class_::_class_(void) { assert(_class_::classTypeId != SoType::badType()); } \
137 _class_::~_class_() { }
138 
139 
140 
141 #define SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
142 void \
143 _class_::setValue(_valref_ valuearg) { \
144  this->value = valuearg; \
145  this->valueChanged(); \
146 } \
147  \
148 SbBool \
149 _class_::operator==(const _class_ & field) const \
150 { \
151  return (this->getValue() == field.getValue()); \
152 }
153 
154 
155 #define PRIVATE_TYPEID_SOURCE(_class_) \
156 SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
157 SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
158 void * _class_::createInstance(void) { return new _class_; } \
159 SoType _class_::classTypeId STATIC_SOTYPE_INIT
160 
161 
162 #define PRIVATE_EQUALITY_SOURCE(_class_) \
163 void \
164 _class_::copyFrom(const SoField & field) \
165 { \
166  this->operator=(static_cast<const _class_ &>(field)); \
167 } \
168  \
169 SbBool \
170 _class_::isSame(const SoField & field) const \
171 { \
172  if (field.getTypeId() != this->getTypeId()) return FALSE; \
173  return this->operator==(static_cast<const _class_ &>(field)); \
174 }
175 
176 
177 
178 #define SO_SFIELD_REQUIRED_SOURCE(_class_) \
179 PRIVATE_TYPEID_SOURCE(_class_); \
180 PRIVATE_EQUALITY_SOURCE(_class_); \
181  \
182 const _class_ & \
183 _class_::operator=(const _class_ & field) \
184 { \
185  this->setValue(field.getValue()); \
186  return *this; \
187 }
188 
189 
190 
191 #define SO_SFIELD_SOURCE(_class_, _valtype_, _valref_) \
192  SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
193  SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_); \
194  SO_SFIELD_REQUIRED_SOURCE(_class_)
195 
196 
197 
198 #define SO_SFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
199  SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
200  SO_SFIELD_REQUIRED_SOURCE(_class_)
201 
202 
203 /**************************************************************************
204  *
205  * Header macros for multiple-value fields.
206  *
207  **************************************************************************/
208 
209 #define PRIVATE_MFIELD_IO_HEADER() \
210 private: \
211  virtual SbBool read1Value(SoInput * in, int idx); \
212  virtual void write1Value(SoOutput * out, int idx) const
213 
214 
215 
216 #define SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
217  PRIVATE_MFIELD_IO_HEADER(); \
218 protected: \
219  virtual void deleteAllValues(void); \
220  virtual void copyValue(int to, int from); \
221  virtual int fieldSizeof(void) const; \
222  virtual void * valuesPtr(void); \
223  virtual void setValuesPtr(void * ptr); \
224  virtual void allocValues(int num); \
225  \
226  _valtype_ * values; \
227 public: \
228  _valref_ operator[](const int idx) const \
229  { this->evaluate(); return this->values[idx]; } \
230  \
233  const _valtype_ * getValues(const int start) const \
234  { this->evaluate(); return const_cast<const _valtype_ *>(this->values + start); } \
235  int find(_valref_ value, SbBool addifnotfound = FALSE); \
236  void setValues(const int start, const int num, const _valtype_ * newvals); \
237  void set1Value(const int idx, _valref_ value); \
238  void setValue(_valref_ value); \
239  _valref_ operator=(_valref_ val) { this->setValue(val); return val; } \
240  SbBool operator==(const _class_ & field) const; \
241  SbBool operator!=(const _class_ & field) const { return !operator==(field); } \
242  _valtype_ * startEditing(void) { this->evaluate(); return this->values; } \
243  void finishEditing(void) { this->valueChanged(); }
244 
245 #define SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
246  PRIVATE_MFIELD_IO_HEADER(); \
247 public: \
248  _valref_ operator=(_valref_ val) { this->setValue(val); return val; }
249 
250 
251 
252 #define SO_MFIELD_HEADER(_class_, _valtype_, _valref_) \
253  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
254  SO_SFIELD_REQUIRED_HEADER(_class_); \
255  SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
256 
257 
258 
259 #define SO_MFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
260  SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
261  SO_SFIELD_REQUIRED_HEADER(_class_); \
262  SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
263 
264 #define SO_MFIELD_SETVALUESPOINTER_HEADER(_valtype_) \
265  void setValuesPointer(const int num, const _valtype_ * userdata); \
266  void setValuesPointer(const int num, _valtype_ * userdata)
267 
268 
269 /**************************************************************************
270  *
271  * Source macros for multiple-value fields.
272  *
273  **************************************************************************/
274 
275 
276 #define SO_MFIELD_INIT_CLASS(_class_, _parent_) \
277  SO_SFIELD_INIT_CLASS(_class_, _parent_)
278 
279 
280 
281 #define SO_MFIELD_CONSTRUCTOR_SOURCE(_class_) \
282 _class_::_class_(void) \
283 { \
284  assert(_class_::classTypeId != SoType::badType()); \
285  this->values = NULL; \
286 } \
287  \
288 _class_::~_class_(void) \
289 { \
290  this->enableNotify(FALSE); /* Avoid notifying destructed containers. */ \
291  this->deleteAllValues(); \
292 }
293 
294 
295 
296 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) \
297 _class_::_class_(void) { } \
298 _class_::~_class_(void) { }
299 
300 
301 
302 #define SO_MFIELD_REQUIRED_SOURCE(_class_) \
303 PRIVATE_TYPEID_SOURCE(_class_); \
304 PRIVATE_EQUALITY_SOURCE(_class_); \
305 const _class_ & \
306 _class_::operator=(const _class_ & field) \
307 { \
308  /* The allocValues() call is needed, as setValues() doesn't */ \
309  /* necessarily make the field's getNum() size become the same */ \
310  /* as the second argument (only if it expands on the old size). */ \
311  this->allocValues(field.getNum()); \
312  \
313  this->setValues(0, field.getNum(), field.getValues(0)); \
314  return *this; \
315 }
316 
317 
318 
319 #define SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
320 int \
321 _class_::fieldSizeof(void) const \
322 { \
323  return sizeof(_valtype_); \
324 } \
325  \
326 void * \
327 _class_::valuesPtr(void) \
328 { \
329  return static_cast<void *>(this->values); \
330 } \
331  \
332 void \
333 _class_::setValuesPtr(void * ptr) \
334 { \
335  this->values = static_cast<_valtype_ *>(ptr); \
336 } \
337  \
338 int \
339 _class_::find(_valref_ value, SbBool addifnotfound) \
340 { \
341  evaluate(); \
342  for (int i=0; i < this->num; i++) if (this->values[i] == value) return i; \
343  \
344  if (addifnotfound) this->set1Value(this->num, value); \
345  return -1; \
346 } \
347  \
348 void \
349 _class_::setValues(const int start, const int numarg, const _valtype_ * newvals) \
350 { \
351  if (start+numarg > this->maxNum) this->allocValues(start+numarg); \
352  else if (start+numarg > this->num) this->num = start+numarg; \
353  \
354  for (int i=0; i < numarg; i++) \
355  this->values[i+start] = static_cast<_valtype_>(newvals[i]); \
356  this->valueChanged(); \
357 } \
358  \
359 void \
360 _class_::set1Value(const int idx, _valref_ value) \
361 { \
362  if (idx+1 > this->maxNum) this->allocValues(idx+1); \
363  else if (idx+1 > this->num) this->num = idx+1; \
364  this->values[idx] = value; \
365  this->valueChanged(); \
366 } \
367  \
368 void \
369 _class_::setValue(_valref_ value) \
370 { \
371  this->allocValues(1); \
372  this->values[0] = value; \
373  this->valueChanged(); \
374 } \
375  \
376 SbBool \
377 _class_::operator==(const _class_ & field) const \
378 { \
379  if (this == &field) return TRUE; \
380  if (this->getNum() != field.getNum()) return FALSE; \
381  \
382  const _valtype_ * const lhs = this->getValues(0); \
383  const _valtype_ * const rhs = field.getValues(0); \
384  for (int i = 0; i < this->num; i++) if (lhs[i] != rhs[i]) return FALSE; \
385  return TRUE; \
386 } \
387  \
388  \
389 void \
390 _class_::deleteAllValues(void) \
391 { \
392  this->setNum(0); \
393 } \
394  \
395  \
396 void \
397 _class_::copyValue(int to, int from) \
398 { \
399  this->values[to] = this->values[from]; \
400 }
401 
402 
403 #define SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_) \
404 void \
405 _class_::allocValues(int newnum) \
406 { \
407  /* Important notice: the "malloc-version" of this method is found */ \
408  /* in SoMField.cpp. If you make modifications here, do check whether */ \
409  /* or not they should be matched with modifications in that method */ \
410  /* aswell. */ \
411  \
412  /* these must be declared here as a gcc 4.0.0 bug workaround */ \
413  int i; \
414  int oldmaxnum; \
415  _valtype_ * newblock; \
416  assert(newnum >= 0); \
417  \
418  if (newnum == 0) { \
419  if (!this->userDataIsUsed) delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
420  this->setValuesPtr(NULL); \
421  this->maxNum = 0; \
422  this->userDataIsUsed = FALSE; \
423  } \
424  else if (newnum > this->maxNum || newnum < this->num) { \
425  if (this->valuesPtr()) { \
426  \
427  /* Allocation strategy is to repeatedly double the size of the */ \
428  /* allocated block until it will at least match the requested size. */ \
429  /* (Unless the requested size is less than what we've got, */ \
430  /* then we'll repeatedly halve the allocation size.) */ \
431  /* */ \
432  /* I think this will handle both cases quite gracefully: */ \
433  /* 1) newnum > this->maxNum, 2) newnum < num */ \
434  oldmaxnum = this->maxNum; \
435  while (newnum > this->maxNum) this->maxNum *= 2; \
436  while ((this->maxNum / 2) >= newnum) this->maxNum /= 2; \
437  \
438  if (oldmaxnum != this->maxNum) { \
439  newblock = new _valtype_[this->maxNum]; \
440  \
441  for (i=0; i < SbMin(this->num, newnum); i++) \
442  newblock[i] = this->values[i]; \
443  \
444  delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
445  this->setValuesPtr(newblock); \
446  this->userDataIsUsed = FALSE; \
447  } \
448  } \
449  else { \
450  this->setValuesPtr(new _valtype_[newnum]); \
451  this->userDataIsUsed = FALSE; \
452  this->maxNum = newnum; \
453  } \
454  } \
455  \
456  this->num = newnum; \
457 }
458 
459 
460 
461 #define SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_) \
462 void \
463 _class_::allocValues(int number) \
464 { \
465  SoMField::allocValues(number); \
466 }
467 
468 
469 
470 #define SO_MFIELD_SOURCE_MALLOC(_class_, _valtype_, _valref_) \
471  SO_MFIELD_REQUIRED_SOURCE(_class_); \
472  SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
473  SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_); \
474  SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
475 
476 
477 
478 #define SO_MFIELD_SOURCE(_class_, _valtype_, _valref_) \
479  SO_MFIELD_REQUIRED_SOURCE(_class_); \
480  SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
481  SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_); \
482  SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
483 
484 
485 #define SO_MFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
486  SO_MFIELD_REQUIRED_SOURCE(_class_); \
487  SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_)
488 
489 #define SO_MFIELD_SETVALUESPOINTER_SOURCE(_class_, _valtype_, _usertype_) \
490 void \
491 _class_::setValuesPointer(const int numarg, _usertype_ * userdata) \
492 { \
493  this->makeRoom(0); \
494  if (numarg > 0 && userdata) { \
495  this->values = reinterpret_cast<_valtype_*>(userdata); /* reinterpret_cast is needed for certain special uses of this function, such as SoMFColor */ \
496  this->userDataIsUsed = TRUE; \
497  this->num = this->maxNum = numarg; \
498  this->valueChanged(); \
499  } \
500 } \
501 void \
502 _class_::setValuesPointer(const int numarg, const _usertype_ * userdata) \
503 { \
504  this->setValuesPointer(numarg, const_cast<_usertype_*>(userdata)); \
505 }
506 
507 #endif // !COIN_SOSUBFIELD_H

Copyright © 1998-2010 by Kongsberg Oil & Gas Technologies. All rights reserved.

Generated on Fri Sep 9 2016 for Coin by Doxygen 1.8.5.