![]() |
http://www.sim.no http://www.coin3d.org |
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-2005 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, Postboks 1283, Pirsenteret, 7462 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 SoType _class_::classTypeId STATIC_SOTYPE_INIT 00156 00157 00158 #define PRIVATE_EQUALITY_SOURCE(_class_) \ 00159 void \ 00160 _class_::copyFrom(const SoField & field) \ 00161 { \ 00162 this->operator=((const _class_ &)field); \ 00163 } \ 00164 \ 00165 SbBool \ 00166 _class_::isSame(const SoField & field) const \ 00167 { \ 00168 if (field.getTypeId() != this->getTypeId()) return FALSE; \ 00169 return this->operator==((const _class_ &) field); \ 00170 } 00171 00172 00173 00174 #define SO_SFIELD_REQUIRED_SOURCE(_class_) \ 00175 PRIVATE_TYPEID_SOURCE(_class_); \ 00176 PRIVATE_EQUALITY_SOURCE(_class_); \ 00177 \ 00178 const _class_ & \ 00179 _class_::operator=(const _class_ & field) \ 00180 { \ 00181 this->setValue(field.getValue()); \ 00182 return *this; \ 00183 } 00184 00185 00186 00187 #define SO_SFIELD_SOURCE(_class_, _valtype_, _valref_) \ 00188 SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \ 00189 SO_SFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_); \ 00190 SO_SFIELD_REQUIRED_SOURCE(_class_) 00191 00192 00193 00194 #define SO_SFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \ 00195 SO_SFIELD_CONSTRUCTOR_SOURCE(_class_); \ 00196 SO_SFIELD_REQUIRED_SOURCE(_class_) 00197 00198 00199 /************************************************************************** 00200 * 00201 * Header macros for multiple-value fields. 00202 * 00203 **************************************************************************/ 00204 00205 #define PRIVATE_MFIELD_IO_HEADER() \ 00206 private: \ 00207 virtual SbBool read1Value(SoInput * in, int idx); \ 00208 virtual void write1Value(SoOutput * out, int idx) const 00209 00210 00211 00212 #define SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) \ 00213 PRIVATE_MFIELD_IO_HEADER(); \ 00214 protected: \ 00215 virtual void deleteAllValues(void); \ 00216 virtual void copyValue(int to, int from); \ 00217 virtual int fieldSizeof(void) const; \ 00218 virtual void * valuesPtr(void); \ 00219 virtual void setValuesPtr(void * ptr); \ 00220 virtual void allocValues(int num); \ 00221 \ 00222 _valtype_ * values; \ 00223 public: \ 00224 _valref_ operator[](const int idx) const \ 00225 { this->evaluate(); return this->values[idx]; } \ 00226 \ 00229 const _valtype_ * getValues(const int start) const \ 00230 { this->evaluate(); return (const _valtype_ *)(this->values + start); } \ 00231 int find(_valref_ value, SbBool addifnotfound = FALSE); \ 00232 void setValues(const int start, const int num, const _valtype_ * newvals); \ 00233 void set1Value(const int idx, _valref_ value); \ 00234 void setValue(_valref_ value); \ 00235 _valref_ operator=(_valref_ val) { this->setValue(val); return val; } \ 00236 SbBool operator==(const _class_ & field) const; \ 00237 SbBool operator!=(const _class_ & field) const { return !operator==(field); } \ 00238 _valtype_ * startEditing(void) { this->evaluate(); return this->values; } \ 00239 void finishEditing(void) { this->valueChanged(); } 00240 00241 #define SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) \ 00242 PRIVATE_MFIELD_IO_HEADER(); \ 00243 public: \ 00244 _valref_ operator=(_valref_ val) { this->setValue(val); return val; } 00245 00246 00247 00248 #define SO_MFIELD_HEADER(_class_, _valtype_, _valref_) \ 00249 SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \ 00250 SO_SFIELD_REQUIRED_HEADER(_class_); \ 00251 SO_MFIELD_VALUE_HEADER(_class_, _valtype_, _valref_) 00252 00253 00254 00255 #define SO_MFIELD_DERIVED_HEADER(_class_, _valtype_, _valref_) \ 00256 SO_SFIELD_CONSTRUCTOR_HEADER(_class_); \ 00257 SO_SFIELD_REQUIRED_HEADER(_class_); \ 00258 SO_MFIELD_DERIVED_VALUE_HEADER(_class_, _valtype_, _valref_) 00259 00260 #define SO_MFIELD_SETVALUESPOINTER_HEADER(_valtype_) \ 00261 void setValuesPointer(const int num, const _valtype_ * userdata); \ 00262 void setValuesPointer(const int num, _valtype_ * userdata) 00263 00264 00265 /************************************************************************** 00266 * 00267 * Source macros for multiple-value fields. 00268 * 00269 **************************************************************************/ 00270 00271 00272 #define SO_MFIELD_INIT_CLASS(_class_, _parent_) \ 00273 SO_SFIELD_INIT_CLASS(_class_, _parent_) 00274 00275 00276 00277 #define SO_MFIELD_CONSTRUCTOR_SOURCE(_class_) \ 00278 _class_::_class_(void) \ 00279 { \ 00280 assert(_class_::classTypeId != SoType::badType()); \ 00281 this->values = NULL; \ 00282 } \ 00283 \ 00284 _class_::~_class_(void) \ 00285 { \ 00286 this->enableNotify(FALSE); /* Avoid notifying destructed containers. */ \ 00287 this->deleteAllValues(); \ 00288 } 00289 00290 00291 00292 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) \ 00293 _class_::_class_(void) { } \ 00294 _class_::~_class_(void) { } 00295 00296 00297 00298 #define SO_MFIELD_REQUIRED_SOURCE(_class_) \ 00299 PRIVATE_TYPEID_SOURCE(_class_); \ 00300 PRIVATE_EQUALITY_SOURCE(_class_); \ 00301 const _class_ & \ 00302 _class_::operator=(const _class_ & field) \ 00303 { \ 00304 /* The allocValues() call is needed, as setValues() doesn't */ \ 00305 /* necessarily make the field's getNum() size become the same */ \ 00306 /* as the second argument (only if it expands on the old size). */ \ 00307 this->allocValues(field.getNum()); \ 00308 \ 00309 this->setValues(0, field.getNum(), field.getValues(0)); \ 00310 return *this; \ 00311 } 00312 00313 00314 00315 #define SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) \ 00316 int \ 00317 _class_::fieldSizeof(void) const \ 00318 { \ 00319 return sizeof(_valtype_); \ 00320 } \ 00321 \ 00322 void * \ 00323 _class_::valuesPtr(void) \ 00324 { \ 00325 return (void *)this->values; \ 00326 } \ 00327 \ 00328 void \ 00329 _class_::setValuesPtr(void * ptr) \ 00330 { \ 00331 this->values = (_valtype_ *)ptr; \ 00332 } \ 00333 \ 00334 int \ 00335 _class_::find(_valref_ value, SbBool addifnotfound) \ 00336 { \ 00337 evaluate(); \ 00338 for (int i=0; i < this->num; i++) if (this->values[i] == value) return i; \ 00339 \ 00340 if (addifnotfound) this->set1Value(this->num, value); \ 00341 return -1; \ 00342 } \ 00343 \ 00344 void \ 00345 _class_::setValues(const int start, const int numarg, const _valtype_ * newvals) \ 00346 { \ 00347 if (start+numarg > this->maxNum) this->allocValues(start+numarg); \ 00348 else if (start+numarg > this->num) this->num = start+numarg; \ 00349 \ 00350 for (int i=0; i < numarg; i++) \ 00351 this->values[i+start] = (_valtype_) newvals[i]; \ 00352 this->valueChanged(); \ 00353 } \ 00354 \ 00355 void \ 00356 _class_::set1Value(const int idx, _valref_ value) \ 00357 { \ 00358 if (idx+1 > this->maxNum) this->allocValues(idx+1); \ 00359 else if (idx+1 > this->num) this->num = idx+1; \ 00360 this->values[idx] = value; \ 00361 this->valueChanged(); \ 00362 } \ 00363 \ 00364 void \ 00365 _class_::setValue(_valref_ value) \ 00366 { \ 00367 this->allocValues(1); \ 00368 this->values[0] = value; \ 00369 this->valueChanged(); \ 00370 } \ 00371 \ 00372 SbBool \ 00373 _class_::operator==(const _class_ & field) const \ 00374 { \ 00375 if (this == &field) return TRUE; \ 00376 if (this->getNum() != field.getNum()) return FALSE; \ 00377 \ 00378 const _valtype_ * const lhs = this->getValues(0); \ 00379 const _valtype_ * const rhs = field.getValues(0); \ 00380 for (int i = 0; i < this->num; i++) if (lhs[i] != rhs[i]) return FALSE; \ 00381 return TRUE; \ 00382 } \ 00383 \ 00384 \ 00385 void \ 00386 _class_::deleteAllValues(void) \ 00387 { \ 00388 this->setNum(0); \ 00389 } \ 00390 \ 00391 \ 00392 void \ 00393 _class_::copyValue(int to, int from) \ 00394 { \ 00395 this->values[to] = this->values[from]; \ 00396 } 00397 00398 00399 #define SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_) \ 00400 void \ 00401 _class_::allocValues(int newnum) \ 00402 { \ 00403 /* Important notice: the "malloc-version" of this method is found */ \ 00404 /* in SoMField.cpp. If you make modifications here, do check whether */ \ 00405 /* or not they should be matched with modifications in that method */ \ 00406 /* aswell. */ \ 00407 \ 00408 assert(newnum >= 0); \ 00409 \ 00410 if (newnum == 0) { \ 00411 if (!this->userDataIsUsed) delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \ 00412 this->setValuesPtr(NULL); \ 00413 this->maxNum = 0; \ 00414 this->userDataIsUsed = FALSE; \ 00415 } \ 00416 else if (newnum > this->maxNum || newnum < this->num) { \ 00417 if (this->valuesPtr()) { \ 00418 \ 00419 /* Allocation strategy is to repeatedly double the size of the */ \ 00420 /* allocated block until it will at least match the requested size. */ \ 00421 /* (Unless the requested size is less than what we've got, */ \ 00422 /* then we'll repeatedly halve the allocation size.) */ \ 00423 /* */ \ 00424 /* I think this will handle both cases quite gracefully: */ \ 00425 /* 1) newnum > this->maxNum, 2) newnum < num */ \ 00426 int oldmaxnum = this->maxNum; \ 00427 while (newnum > this->maxNum) this->maxNum *= 2; \ 00428 while ((this->maxNum / 2) >= newnum) this->maxNum /= 2; \ 00429 \ 00430 if (oldmaxnum != this->maxNum) { \ 00431 _valtype_ * newblock = new _valtype_[this->maxNum]; \ 00432 this->userDataIsUsed = FALSE; \ 00433 \ 00434 for (int i=0; i < SbMin(this->num, newnum); i++) \ 00435 newblock[i] = this->values[i]; \ 00436 \ 00437 delete[] this->values; /* don't fetch pointer through valuesPtr() (avoids void* cast) */ \ 00438 this->setValuesPtr(newblock); \ 00439 } \ 00440 } \ 00441 else { \ 00442 this->setValuesPtr(new _valtype_[newnum]); \ 00443 this->userDataIsUsed = FALSE; \ 00444 this->maxNum = newnum; \ 00445 } \ 00446 } \ 00447 \ 00448 this->num = newnum; \ 00449 } 00450 00451 00452 00453 #define SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_) \ 00454 void \ 00455 _class_::allocValues(int number) \ 00456 { \ 00457 SoMField::allocValues(number); \ 00458 } 00459 00460 00461 00462 #define SO_MFIELD_SOURCE_MALLOC(_class_, _valtype_, _valref_) \ 00463 SO_MFIELD_REQUIRED_SOURCE(_class_); \ 00464 SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \ 00465 SO_MFIELD_MALLOC_SOURCE(_class_, _valtype_); \ 00466 SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) 00467 00468 00469 00470 #define SO_MFIELD_SOURCE(_class_, _valtype_, _valref_) \ 00471 SO_MFIELD_REQUIRED_SOURCE(_class_); \ 00472 SO_MFIELD_CONSTRUCTOR_SOURCE(_class_); \ 00473 SO_MFIELD_ALLOC_SOURCE(_class_, _valtype_); \ 00474 SO_MFIELD_VALUE_SOURCE(_class_, _valtype_, _valref_) 00475 00476 00477 #define SO_MFIELD_DERIVED_SOURCE(_class_, _valtype_, _valref_) \ 00478 SO_MFIELD_REQUIRED_SOURCE(_class_); \ 00479 SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(_class_) 00480 00481 #define SO_MFIELD_SETVALUESPOINTER_SOURCE(_class_, _valtype_, _usertype_) \ 00482 void \ 00483 _class_::setValuesPointer(const int numarg, _usertype_ * userdata) \ 00484 { \ 00485 this->makeRoom(0); \ 00486 if (numarg > 0 && userdata) { \ 00487 this->values = (_valtype_*) userdata; \ 00488 this->userDataIsUsed = TRUE; \ 00489 this->num = this->maxNum = numarg; \ 00490 this->valueChanged(); \ 00491 } \ 00492 } \ 00493 void \ 00494 _class_::setValuesPointer(const int numarg, const _usertype_ * userdata) \ 00495 { \ 00496 this->setValuesPointer(numarg, (_usertype_*) userdata); \ 00497 } 00498 00499 #endif // !COIN_SOSUBFIELD_H
Copyright © 1998-2005 by Systems in Motion AS. All rights reserved.
Generated on Sun Aug 21 16:51:12 2005 for Coin by Doxygen. 1.3.9.1