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_) \
46public: \
47 _class_(void); \
48 virtual ~_class_()
49
50
51#define SO_SFIELD_REQUIRED_HEADER(_class_) \
52private: \
53 static SoType classTypeId; \
54 static void atexit_cleanup(void) { SoType::removeType(_class_::classTypeId.getName()); _class_::classTypeId STATIC_SOTYPE_INIT; } \
55public: \
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() \
66private: \
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(); \
73protected: \
74 _valtype_ value; \
75 \
76public: \
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(); \
89public: \
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_) \
142void \
143_class_::setValue(_valref_ valuearg) { \
144 this->value = valuearg; \
145 this->valueChanged(); \
146} \
147 \
148SbBool \
149_class_::operator==(const _class_ & field) const \
150{ \
151 return (this->getValue() == field.getValue()); \
152}
153
154
155#define PRIVATE_TYPEID_SOURCE(_class_) \
156SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
157SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
158void * _class_::createInstance(void) { return new _class_; } \
159SoType _class_::classTypeId STATIC_SOTYPE_INIT
160
161
162#define PRIVATE_EQUALITY_SOURCE(_class_) \
163void \
164_class_::copyFrom(const SoField & field) \
165{ \
166 this->operator=(static_cast<const _class_ &>(field)); \
167} \
168 \
169SbBool \
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_) \
179PRIVATE_TYPEID_SOURCE(_class_); \
180PRIVATE_EQUALITY_SOURCE(_class_); \
181 \
182const _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() \
210private: \
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(); \
218protected: \
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; \
227public: \
228 _valref_ operator[](const int idx) const \
229 { this->evaluate(); return this->values[idx]; } \
230
232 \
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(); \
247public: \
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_) \
303PRIVATE_TYPEID_SOURCE(_class_); \
304PRIVATE_EQUALITY_SOURCE(_class_); \
305const _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_) \
320int \
321_class_::fieldSizeof(void) const \
322{ \
323 return sizeof(_valtype_); \
324} \
325 \
326void * \
327_class_::valuesPtr(void) \
328{ \
329 return static_cast<void *>(this->values); \
330} \
331 \
332void \
333_class_::setValuesPtr(void * ptr) \
334{ \
335 this->values = static_cast<_valtype_ *>(ptr); \
336} \
337 \
338int \
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 \
348void \
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 \
359void \
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 \
368void \
369_class_::setValue(_valref_ value) \
370{ \
371 this->allocValues(1); \
372 this->values[0] = value; \
373 this->valueChanged(); \
374} \
375 \
376SbBool \
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 \
389void \
390_class_::deleteAllValues(void) \
391{ \
392 this->setNum(0); \
393} \
394 \
395 \
396void \
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_) \
404void \
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_) \
462void \
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_) \
490void \
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} \
501void \
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 Wed Jul 17 2024 for Coin by Doxygen 1.12.0.