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

Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

SoSubField.h

00001 #ifndef COIN_SOSUBFIELD_H
00002 #define COIN_SOSUBFIELD_H
00003 
00004 /**************************************************************************\
00005  *
00006  *  This file is part of the Coin 3D visualization library.
00007  *  Copyright (C) 1998-2004 by Systems in Motion.  All rights reserved.
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU General Public License
00011  *  ("GPL") version 2 as published by the Free Software Foundation.
00012  *  See the file LICENSE.GPL at the root directory of this source
00013  *  distribution for additional information about the GNU GPL.
00014  *
00015  *  For using Coin with software that can not be combined with the GNU
00016  *  GPL, and for taking advantage of the additional benefits of our
00017  *  support services, please contact Systems in Motion about acquiring
00018  *  a Coin Professional Edition License.
00019  *
00020  *  See <URL:http://www.coin3d.org/> for more information.
00021  *
00022  *  Systems in Motion, Teknobyen, Abels Gate 5, 7030 Trondheim, NORWAY.
00023  *  <URL:http://www.sim.no/>.
00024  *
00025 \**************************************************************************/
00026 
00027 #include <Inventor/SbBasic.h> // for SO__QUOTE() definition
00028 #include <Inventor/SbName.h> // SoType::createType() needs to know SbName.
00029 #include <assert.h>
00030 
00031 #ifndef COIN_INTERNAL
00032 // Added to be Inventor compliant.
00033 #include <Inventor/fields/SoField.h>
00034 #include <Inventor/SoInput.h>
00035 #include <Inventor/SoOutput.h>
00036 #endif // !COIN_INTERNAL
00037 
00038 /**************************************************************************
00039  *
00040  * Header macros for single-value fields.
00041  *
00042  **************************************************************************/
00043 
00044 #define SO_SFIELD_CONSTRUCTOR_HEADER(_class_) \
00045 public: \
00046   _class_(void); \
00047   virtual ~_class_()
00048 
00049 
00050 #define SO_SFIELD_REQUIRED_HEADER(_class_) \
00051 private: \
00052   static SoType classTypeId; \
00053 public: \
00054   static void * createInstance(void); \
00055   static SoType getClassTypeId(void); \
00056   virtual SoType getTypeId(void) const; \
00057  \
00058   virtual void copyFrom(const SoField & field); \
00059   const _class_ & operator=(const _class_ & field); \
00060   virtual SbBool isSame(const SoField & field) const
00061 
00062 
00063 #define PRIVATE_SFIELD_IO_HEADER() \
00064 private: \
00065   virtual SbBool readValue(SoInput * in); \
00066   virtual void writeValue(SoOutput * out) const
00067 
00068 
00069 #define SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
00070   PRIVATE_SFIELD_IO_HEADER(); \
00071 protected: \
00072   _valtype_ value; \
00073  \
00074 public: \
00075   _valref_ getValue(void) const { this->evaluate(); return this->value; } \
00076   void setValue(_valref_ newvalue); \
00077   _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; } \
00078  \
00079   int operator==(const _class_ & field) const; \
00080   int operator!=(const _class_ & field) const { return ! operator==(field); }
00081 
00082 
00083 // FIXME: is really the operator=() definition below necessary?
00084 // 19991226 mortene.
00085 #define SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
00086   PRIVATE_SFIELD_IO_HEADER(); \
00087 public: \
00088   _valref_ operator=(_valref_ newvalue) { this->setValue(newvalue); return this->value; }
00089 
00090 
00091 
00092 #define SO_SFIELD_HEADER(_class_, _valtype_, _valref_) \
00093   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
00094   SO_SFIELD_REQUIRED_HEADER(_class_); \
00095   SO_SFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
00096 
00097 
00098 #define SO_SFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
00099   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
00100   SO_SFIELD_REQUIRED_HEADER(_class_); \
00101   SO_SFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
00102 
00103 
00104 
00105 /**************************************************************************
00106  *
00107  * Source macros for single-value fields.
00108  *
00109  **************************************************************************/
00110 
00111 #define PRIVATE_FIELD_INIT_CLASS(_class_, _classname_, _parent_, _createfunc_) \
00112   do { \
00113     /* Make sure superclass get initialized before subclass. */ \
00114     assert(_parent_::getClassTypeId() != SoType::badType()); \
00115     /* Make sure we only initialize once. */ \
00116     assert(_class_::classTypeId == SoType::badType()); \
00117     _class_::classTypeId = \
00118       SoType::createType(_parent_::getClassTypeId(), _classname_, _createfunc_); \
00119   } while (0)
00120 
00121 
00122 
00123 #define SO_SFIELD_INIT_CLASS(_class_, _parent_) \
00124   do { \
00125     const char * classname = SO__QUOTE(_class_); \
00126     PRIVATE_FIELD_INIT_CLASS(_class_, classname, _parent_, &_class_::createInstance); \
00127   } while (0)
00128 
00129 
00130 
00131 #define SO_SFIELD_CONSTRUCTOR_SOURCE(_class_) \
00132 _class_::_class_(void) { assert(_class_::classTypeId != SoType::badType()); } \
00133 _class_::~_class_() { }
00134 
00135 
00136 
00137 #define SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
00138 void \
00139 _class_::setValue(_valref_ valuearg) { \
00140   this->value = valuearg; \
00141   this->valueChanged(); \
00142 } \
00143  \
00144 SbBool \
00145 _class_::operator==(const _class_ & field) const \
00146 { \
00147   return (this->getValue() == field.getValue()); \
00148 }
00149 
00150 
00151 #define PRIVATE_TYPEID_SOURCE(_class_) \
00152 SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
00153 SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
00154 void * _class_::createInstance(void) { return new _class_; } \
00155 /* Don't set value explicitly to SoType::badType(), to avoid a bug in */ \
00156 /* Sun CC v4.0. (Bitpattern 0x0000 equals SoType::badType()). */ \
00157 SoType _class_::classTypeId
00158 
00159 
00160 #define PRIVATE_EQUALITY_SOURCE(_class_) \
00161 void \
00162 _class_::copyFrom(const SoField & field) \
00163 { \
00164   this->operator=((const _class_ &)field); \
00165 } \
00166  \
00167 SbBool \
00168 _class_::isSame(const SoField & field) const \
00169 { \
00170   if (field.getTypeId() != this->getTypeId()) return FALSE; \
00171   return this->operator==((const _class_ &) field); \
00172 }
00173 
00174 
00175 
00176 #define SO_SFIELD_REQUIRED_SOURCE(_class_) \
00177 PRIVATE_TYPEID_SOURCE(_class_); \
00178 PRIVATE_EQUALITY_SOURCE(_class_); \
00179  \
00180 const _class_ & \
00181 _class_::operator=(const _class_ & field) \
00182 { \
00183   this->setValue(field.getValue()); \
00184   return *this; \
00185 }
00186 
00187 
00188 
00189 #define SO_SFIELD_SOURCE(_class_, _valtype_, _valref_) \
00190   SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
00191   SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_); \
00192   SO_SFIELD_REQUIRED_SOURCE(_class_)
00193 
00194 
00195 
00196 #define SO_SFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
00197   SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \
00198   SO_SFIELD_REQUIRED_SOURCE(_class_)
00199 
00200 
00201 /**************************************************************************
00202  *
00203  * Header macros for multiple-value fields.
00204  *
00205  **************************************************************************/
00206 
00207 #define PRIVATE_MFIELD_IO_HEADER() \
00208 private: \
00209   virtual SbBool read1Value(SoInput * in, int idx); \
00210   virtual void write1Value(SoOutput * out, int idx) const
00211 
00212 
00213 
00214 #define SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \
00215   PRIVATE_MFIELD_IO_HEADER(); \
00216 protected: \
00217   virtual void deleteAllValues(void); \
00218   virtual void copyValue(int to, int from); \
00219   virtual int fieldSizeof(void) const; \
00220   virtual void * valuesPtr(void); \
00221   virtual void setValuesPtr(void * ptr); \
00222   virtual void allocValues(int num); \
00223  \
00224   _valtype_ * values; \
00225 public: \
00226   _valref_ operator[](const int idx) const \
00227     { this->evaluate(); return this->values[idx]; } \
00228   const _valtype_ * getValues(const int start) const \
00229     { this->evaluate(); return (const _valtype_ *)(this->values + start); } \
00230   int find(_valref_ value, SbBool addifnotfound = FALSE); \
00231   void setValues(const int start, const int num, const _valtype_ * newvals); \
00232   void set1Value(const int idx, _valref_ value); \
00233   void setValue(_valref_ value); \
00234   _valref_ operator=(_valref_ val) { this->setValue(val); return val; } \
00235   SbBool operator==(const _class_ & field) const; \
00236   SbBool operator!=(const _class_ & field) const { return !operator==(field); } \
00237   _valtype_ * startEditing(void) { this->evaluate(); return this->values; } \
00238   void finishEditing(void) { this->valueChanged(); }
00239 
00240 #define SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \
00241   PRIVATE_MFIELD_IO_HEADER(); \
00242 public: \
00243   _valref_ operator=(_valref_ val) { this->setValue(val); return val; }
00244 
00245 
00246 
00247 #define SO_MFIELD_HEADER(_class_, _valtype_, _valref_) \
00248   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
00249   SO_SFIELD_REQUIRED_HEADER(_class_); \
00250   SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_)
00251 
00252 
00253 
00254 #define SO_MFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \
00255   SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \
00256   SO_SFIELD_REQUIRED_HEADER(_class_); \
00257   SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_)
00258 
00259 #define SO_MFIELD_SETVALUESPOINTER_HEADER(_valtype_) \
00260   void setValuesPointer(const int num, const _valtype_ * userdata); \
00261   void setValuesPointer(const int num, _valtype_ * userdata)
00262 
00263    
00264 /**************************************************************************
00265  *
00266  * Source macros for multiple-value fields.
00267  *
00268  **************************************************************************/
00269 
00270 
00271 #define SO_MFIELD_INIT_CLASS(_class_, _parent_) \
00272   SO_SFIELD_INIT_CLASS(_class_, _parent_)
00273 
00274 
00275 
00276 #define SO_MFIELD_CONSTRUCTOR_SOURCE(_class_) \
00277 _class_::_class_(void) \
00278 { \
00279   assert(_class_::classTypeId != SoType::badType()); \
00280   this->values = NULL; \
00281 } \
00282  \
00283 _class_::~_class_(void) \
00284 { \
00285   this->enableNotify(FALSE); /* Avoid notifying destructed containers. */ \
00286   this->deleteAllValues(); \
00287 }
00288 
00289 
00290 
00291 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) \
00292 _class_::_class_(void) { } \
00293 _class_::~_class_(void) { }
00294 
00295 
00296 
00297 #define SO_MFIELD_REQUIRED_SOURCE(_class_) \
00298 PRIVATE_TYPEID_SOURCE(_class_); \
00299 PRIVATE_EQUALITY_SOURCE(_class_); \
00300 const _class_ & \
00301 _class_::operator=(const _class_ & field) \
00302 { \
00303   /* The allocValues() call is needed, as setValues() doesn't */ \
00304   /* necessarily make the field's getNum() size become the same */ \
00305   /* as the second argument (only if it expands on the old size). */ \
00306   this->allocValues(field.getNum()); \
00307   \
00308   this->setValues(0, field.getNum(), field.getValues(0)); \
00309   return *this; \
00310 }
00311 
00312 
00313 
00314 #define SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \
00315 int \
00316 _class_::fieldSizeof(void) const \
00317 { \
00318   return sizeof(_valtype_); \
00319 } \
00320  \
00321 void * \
00322 _class_::valuesPtr(void) \
00323 { \
00324   return (void *)this->values; \
00325 } \
00326  \
00327 void \
00328 _class_::setValuesPtr(void * ptr) \
00329 { \
00330   this->values = (_valtype_ *)ptr; \
00331 } \
00332  \
00333 int \
00334 _class_::find(_valref_ value, SbBool addifnotfound) \
00335 { \
00336   for (int i=0; i < this->num; i++) if (this->values[i] == value) return i; \
00337  \
00338   if (addifnotfound) this->set1Value(this->num, value); \
00339   return -1; \
00340 } \
00341  \
00342 void \
00343 _class_::setValues(const int start, const int numarg, const _valtype_ * newvals) \
00344 { \
00345   if (start+numarg > this->maxNum) this->allocValues(start+numarg); \
00346   else if (start+numarg > this->num) this->num = start+numarg; \
00347  \
00348   for (int i=0; i < numarg; i++) \
00349     this->values[i+start] = (_valtype_) newvals[i]; \
00350   this->valueChanged(); \
00351 } \
00352  \
00353 void \
00354 _class_::set1Value(const int idx, _valref_ value) \
00355 { \
00356   if (idx+1 > this->maxNum) this->allocValues(idx+1); \
00357   else if (idx+1 > this->num) this->num = idx+1; \
00358   this->values[idx] = value; \
00359   this->valueChanged(); \
00360 } \
00361  \
00362 void \
00363 _class_::setValue(_valref_ value) \
00364 { \
00365   this->allocValues(1); \
00366   this->values[0] = value; \
00367   this->valueChanged(); \
00368 } \
00369  \
00370 SbBool \
00371 _class_::operator==(const _class_ & field) const \
00372 { \
00373   if (this == &field) return TRUE; \
00374   if (this->getNum() != field.getNum()) return FALSE; \
00375  \
00376   const _valtype_ * const lhs = this->getValues(0); \
00377   const _valtype_ * const rhs = field.getValues(0); \
00378   for (int i = 0; i < this->num; i++) if (lhs[i] != rhs[i]) return FALSE; \
00379   return TRUE; \
00380 } \
00381  \
00382  \
00383 void \
00384 _class_::deleteAllValues(void) \
00385 { \
00386   this->setNum(0); \
00387 } \
00388  \
00389  \
00390 void \
00391 _class_::copyValue(int to, int from) \
00392 { \
00393   this->values[to] = this->values[from]; \
00394 }
00395 
00396 
00397 #define SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_) \
00398 void \
00399 _class_::allocValues(int newnum) \
00400 { \
00401   /* Important notice: the "malloc-version" of this method is found */ \
00402   /* in SoMField.cpp. If you make modifications here, do check whether */ \
00403   /* or not they should be matched with modifications in that method */ \
00404   /* aswell. */ \
00405  \
00406   assert(newnum >= 0); \
00407  \
00408   if (newnum == 0) { \
00409     if (!this->userDataIsUsed) delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
00410     this->setValuesPtr(NULL); \
00411     this->maxNum = 0; \
00412     this->userDataIsUsed = FALSE; \
00413   } \
00414   else if (newnum > this->maxNum || newnum < this->num) { \
00415     if (this->valuesPtr()) { \
00416  \
00417       /* Allocation strategy is to repeatedly double the size of the */ \
00418       /* allocated block until it will at least match the requested size. */ \
00419       /* (Unless the requested size is less than what we've got, */ \
00420       /* then we'll repeatedly halve the allocation size.) */ \
00421       /* */ \
00422       /* I think this will handle both cases quite gracefully: */ \
00423       /* 1) newnum > this->maxNum, 2) newnum < num */ \
00424       int oldmaxnum = this->maxNum; \
00425       while (newnum > this->maxNum) this->maxNum *= 2; \
00426       while ((this->maxNum / 2) >= newnum) this->maxNum /= 2; \
00427  \
00428       if (oldmaxnum != this->maxNum) { \
00429         _valtype_ * newblock = new _valtype_[this->maxNum]; \
00430         this->userDataIsUsed = FALSE; \
00431  \
00432         for (int i=0; i < SbMin(this->num, newnum); i++) \
00433           newblock[i] = this->values[i]; \
00434  \
00435         delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \
00436         this->setValuesPtr(newblock); \
00437       } \
00438     } \
00439     else { \
00440       this->setValuesPtr(new _valtype_[newnum]); \
00441       this->userDataIsUsed = FALSE; \
00442       this->maxNum = newnum; \
00443     } \
00444   } \
00445  \
00446   this->num = newnum; \
00447 }
00448 
00449 
00450 
00451 #define SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_) \
00452 void \
00453 _class_::allocValues(int number) \
00454 { \
00455   SoMField::allocValues(number); \
00456 }
00457 
00458 
00459 
00460 #define SO_MFIELD_SOURCE_MALLOC(_class_, _valtype_, _valref_) \
00461   SO_MFIELD_REQUIRED_SOURCE(_class_); \
00462   SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
00463   SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_); \
00464   SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
00465 
00466 
00467 
00468 #define SO_MFIELD_SOURCE(_class_, _valtype_, _valref_) \
00469   SO_MFIELD_REQUIRED_SOURCE(_class_); \
00470   SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \
00471   SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_); \
00472   SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_)
00473 
00474 
00475 #define SO_MFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \
00476   SO_MFIELD_REQUIRED_SOURCE(_class_); \
00477   SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_)
00478 
00479 #define SO_MFIELD_SETVALUESPOINTER_SOURCE(_class_, _valtype_, _usertype_) \
00480 void \
00481 _class_::setValuesPointer(const int numarg, _usertype_ * userdata) \
00482 { \
00483   this->makeRoom(0); \
00484   if (numarg > 0 && userdata) { \
00485     this->values = (_valtype_*) userdata; \
00486     this->userDataIsUsed = TRUE; \
00487     this->num = this->maxNum = numarg; \
00488     this->valueChanged(); \
00489   } \
00490 } \
00491 void \
00492 _class_::setValuesPointer(const int numarg, const _usertype_ * userdata) \
00493 { \
00494   this->setValuesPointer(numarg, (_usertype_*) userdata); \
00495 }
00496 
00497 #endif // !COIN_SOSUBFIELD_H

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

Generated on Tue Jul 13 06:40:43 2004 for Coin by Doxygen. 1.3.4