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

Copyright © 1998-2007 by Systems in Motion AS. All rights reserved.

Generated on Fri Jul 20 2018 for Coin by Doxygen. 1.8.14