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