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_) \
54public: \
55 _class_(void); \
56 virtual ~_class_()
57
58
59#define SO_SFIELD_REQUIRED_HEADER(_class_) \
60private: \
61 static SoType classTypeId; \
62 static void atexit_cleanup(void) { _class_::classTypeId STATIC_SOTYPE_INIT; } \
63public: \
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() \
74private: \
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(); \
81protected: \
82 _valtype_ value; \
83 \
84public: \
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(); \
97public: \
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_) \
146void \
147_class_::setValue(_valref_ valuearg) { \
148 this->value = valuearg; \
149 this->valueChanged(); \
150} \
151 \
152SbBool \
153_class_::operator==(const _class_ & field) const \
154{ \
155 return (this->getValue() == field.getValue()); \
156}
157
158
159#define PRIVATE_TYPEID_SOURCE(_class_) \
160SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \
161SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \
162void * _class_::createInstance(void) { return new _class_; } \
163SoType _class_::classTypeId STATIC_SOTYPE_INIT
164
165
166#define PRIVATE_EQUALITY_SOURCE(_class_) \
167void \
168_class_::copyFrom(const SoField & field) \
169{ \
170 this->operator=((const _class_ &)field); \
171} \
172 \
173SbBool \
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_) \
183PRIVATE_TYPEID_SOURCE(_class_); \
184PRIVATE_EQUALITY_SOURCE(_class_); \
185 \
186const _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() \
214private: \
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(); \
222protected: \
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; \
231public: \
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(); \
251public: \
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_) \
307PRIVATE_TYPEID_SOURCE(_class_); \
308PRIVATE_EQUALITY_SOURCE(_class_); \
309const _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_) \
324int \
325_class_::fieldSizeof(void) const \
326{ \
327 return sizeof(_valtype_); \
328} \
329 \
330void * \
331_class_::valuesPtr(void) \
332{ \
333 return (void *)this->values; \
334} \
335 \
336void \
337_class_::setValuesPtr(void * ptr) \
338{ \
339 this->values = (_valtype_ *)ptr; \
340} \
341 \
342int \
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 \
352void \
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 \
363void \
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 \
372void \
373_class_::setValue(_valref_ value) \
374{ \
375 this->allocValues(1); \
376 this->values[0] = value; \
377 this->valueChanged(); \
378} \
379 \
380SbBool \
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 \
393void \
394_class_::deleteAllValues(void) \
395{ \
396 this->setNum(0); \
397} \
398 \
399 \
400void \
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_) \
408void \
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_) \
466void \
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_) \
494void \
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} \
505void \
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 Wed Jul 23 2025 for Coin by Doxygen. 1.14.0