Open Inventor Reference
SoSubField.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * Further, this software is distributed without any warranty that it is
16  * free of the rightful claim of any third person regarding infringement
17  * or the like. Any license provided herein, whether implied or
18  * otherwise, applies only to this software file. Patent licenses, if
19  * any, provided herein do not apply to combinations of this program with
20  * other software, or any other product whatsoever.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
27  * Mountain View, CA 94043, or:
28  *
29  * http://www.sgi.com
30  *
31  * For further information regarding this notice, see:
32  *
33  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
34  *
35  */
36 
37 
38 /*
39  * Copyright (C) 1990,91 Silicon Graphics, Inc.
40  *
41  _______________________________________________________________________
42  ______________ S I L I C O N G R A P H I C S I N C . ____________
43  |
44  | $Revision: 1.1.1.1 $
45  |
46  | Description:
47  | This file defines some macros that implement things common to
48  | many subclasses of SoField (actually, subclasses of SoSField
49  | and SoMField). They may be used to make subclassing easier.
50  | In the macros, the following parameters are used consistently:
51  |
52  | className = name of new field subclass
53  |
54  | valueType = type of field value (e.g., float, SbVec3f)
55  |
56  | valueRef = type of field value that can be passed or
57  | returned. For simple types like float or
58  | int, it is the same as valueType. For
59  | aggregates such as SbVec3f, use a const
60  | reference, e.g.: const SbVec3f &
61  |
62  | Macros for single-value (SoSField) field subclasses:
63  |
64  | Within class header:
65  |
66  | SO_SFIELD_REQUIRED_HEADER()
67  | SO_SFIELD_CONSTRUCTOR_HEADER()
68  | SO_SFIELD_VALUE_HEADER()
69  | SO_SFIELD_DERIVED_VALUE_HEADER()
70  |
71  | SO_SFIELD_HEADER()
72  | [includes REQUIRED, CONSTRUCTOR, and VALUE]
73  | SO_SFIELD_DERIVED_HEADER()
74  | [includes REQUIRED, CONSTRUCTOR, and DERIVED_VALUE]
75  |
76  | Within class source:
77  |
78  | SO_SFIELD_INIT_CLASS()
79  | SO_SFIELD_REQUIRED_SOURCE()
80  | SO_SFIELD_CONSTRUCTOR_SOURCE()
81  | SO_SFIELD_VALUE_SOURCE()
82  |
83  | SO_SFIELD_SOURCE()
84  | [includes REQUIRED, CONSTRUCTOR, and VALUE]
85  | SO_SFIELD_DERIVED_SOURCE()
86  | [includes REQUIRED and CONSTRUCTOR]
87  |
88  | Macros for multiple-value (SoMField) field subclasses:
89  |
90  | Within class header:
91  |
92  | SO_MFIELD_REQUIRED_HEADER()
93  | SO_MFIELD_CONSTRUCTOR_HEADER()
94  | SO_MFIELD_VALUE_HEADER()
95  | SO_MFIELD_DERIVED_VALUE_HEADER()
96  |
97  | SO_MFIELD_HEADER()
98  | [includes REQUIRED, CONSTRUCTOR, and VALUE]
99  | SO_MFIELD_DERIVED_HEADER()
100  | [includes REQUIRED and DERIVED_VALUE ]
101  |
102  | Within class source:
103  |
104  | SO_MFIELD_INIT_CLASS()
105  | SO_MFIELD_REQUIRED_SOURCE()
106  | SO_MFIELD_CONSTRUCTOR_SOURCE()
107  | SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE()
108  | SO_MFIELD_VALUE_SOURCE()
109  | SO_MFIELD_ALLOC_SOURCE()
110  | SO_MFIELD_MALLOC_SOURCE()
111  |
112  | SO_MFIELD_SOURCE()
113  | [includes REQUIRED, CONSTRUCTOR, VALUE, and ALLOC]
114  | SO_MFIELD_SOURCE_MALLOC()
115  | [includes REQUIRED, CONSTRUCTOR, VALUE, and MALLOC]
116  | SO_MFIELD_DERIVED_SOURCE()
117  | [includes REQUIRED and DERIVED_CONSTRUCTOR]
118  |
119  | Author(s) : Paul S. Strauss
120  |
121  ______________ S I L I C O N G R A P H I C S I N C . ____________
122  _______________________________________________________________________
123  */
124 
125 #ifndef _SO_SUB_FIELD_
126 #define _SO_SUB_FIELD_
127 
129 #include <Inventor/fields/SoField.h>
130 #include <Inventor/SoInput.h>
131 #include <Inventor/SoOutput.h>
132 
133 
139 
140 #define SO__FIELD_HEADER(className) \
141  public: \
142  virtual SoType getTypeId() const; \
143  static SoType getClassTypeId() { return classTypeId; } \
144  \
145  /* Copy from another field of same type */ \
146  const className & operator =(const className &f); \
147  \
148  SoINTERNAL public: \
149  /* Copy from another field of unknown type (assumed to be same type) */ \
150  virtual void copyFrom(const SoField &f); \
151  \
152  static void * createInstance(); /* for SoType */ \
153  \
154  /* Returns TRUE if fields are same type and have same values */ \
155  virtual bool isSame(const SoField &f) const; \
156  \
157  private: \
158  static SoType classTypeId
159 
160 #define SO__SFIELD_RW_HEADER(className) \
161  private: \
162  /* Reads value of field from file */ \
163  virtual bool readValue(SoInput *in); \
164  \
165  /* Writes value of field to file */ \
166  virtual void writeValue(SoOutput *out) const
167 
168 #define SO__MFIELD_RW_HEADER(className) \
169  private: \
170  /* Reads indexed value of field from file */ \
171  virtual bool read1Value(SoInput *in, int index); \
172  \
173  /* Writes one (indexed) value to file */ \
174  virtual void write1Value(SoOutput *out, int index) const
175 
176 #define SO__FIELD_INIT_CLASS(className,classPrintName,parentClass) \
177  classTypeId = SoType::createType(parentClass::getClassTypeId(), \
178  classPrintName, \
179  &className::createInstance)
180 
181 #define SO__FIELD_ID_SOURCE(className) \
182  \
183 SoType className::classTypeId; \
184  \
185 SoType \
186 className::getTypeId() const \
187 { \
188  return classTypeId; \
189 } \
190 void * \
191 className::createInstance() \
192 { \
193  return static_cast<void *>(new className); \
194 }
195 
196 #define SO__FIELD_EQ_SAME_SOURCE(className) \
197  \
198 void \
199 className::copyFrom(const SoField &f) \
200 { \
201  *this = * static_cast<const className *>(&f); \
202 } \
203  \
204 bool \
205 className::isSame(const SoField &f) const \
206 { \
207  return (getTypeId() == f.getTypeId() && \
208  (*this) == static_cast<const className &>(f)); \
209 }
210 
217 
223 
224 #define SO_SFIELD_REQUIRED_HEADER(className) \
225  SO__FIELD_HEADER(className)
226 
232 
233 #define SO_SFIELD_CONSTRUCTOR_HEADER(className) \
234  public: \
235  className(); \
236  virtual ~className()
237 
244 
245 #define SO_SFIELD_VALUE_HEADER(className, valueType, valueRef) \
246  SO__SFIELD_RW_HEADER(className); \
247  public: \
248  /* Get the value */ \
249  valueRef getValue() const \
250  { evaluate(); return value; } \
251  \
252  /* Set value from a value of the appropriate type */ \
253  void setValue(valueRef newValue); \
254  valueRef operator =(valueRef newValue) \
255  { setValue(newValue); return value; } \
256  \
257  /* Equality/inequality test for fields of same type */ \
258  bool operator ==(const className &f) const; \
259  bool operator !=(const className &f) const \
260  { return ! ((*this) == f); } \
261  \
262  protected: \
263  valueType value
264 
272 
273 #define SO_SFIELD_DERIVED_VALUE_HEADER(className, valueType, valueRef) \
274  SO__SFIELD_RW_HEADER(className); \
275  public: \
276  /* Since = operator is not inherited, we redefine it here */ \
277  valueRef operator =(valueRef newValue) \
278  { setValue(newValue); return value; }
279 
286 
287 #define SO_SFIELD_HEADER(className, valueType, valueRef) \
288  SO_SFIELD_REQUIRED_HEADER(className); \
289  SO_SFIELD_CONSTRUCTOR_HEADER(className); \
290  SO_SFIELD_VALUE_HEADER(className, valueType, valueRef)
291 
299 
300 #define SO_SFIELD_DERIVED_HEADER(className, valueType, valueRef) \
301  SO_SFIELD_REQUIRED_HEADER(className); \
302  SO_SFIELD_CONSTRUCTOR_HEADER(className); \
303  SO_SFIELD_DERIVED_VALUE_HEADER(className, valueType, valueRef)
304 
311 
317 
318 #define SO_MFIELD_REQUIRED_HEADER(className) \
319  SO__FIELD_HEADER(className)
320 
326 
327 #define SO_MFIELD_CONSTRUCTOR_HEADER(className) \
328  public: \
329  className(); \
330  virtual ~className()
331 
338 
339 #define SO_MFIELD_VALUE_HEADER(className, valueType, valueRef) \
340  SO__MFIELD_RW_HEADER(className); \
341  public: \
342  /* Get indexed value */ \
343  valueRef operator [](int i) const \
344  { evaluate(); return values[i]; } \
345  \
346  /* Get pointer into array of values */ \
347  const valueType * getValues(int start) const \
348  { evaluate(); return const_cast<const valueType *>(values + start); } \
349  \
350  /* Finds index of value that is equal to given one, or -1 if not */ \
351  /* found. If not found and addIfNotFound is TRUE, the new value is */ \
352  /* appended to the field. */ \
353  int find(valueRef targetValue, \
354  bool addIfNotFound = FALSE); \
355  \
356  /* Set num values starting at index start from info in newValues */ \
357  void setValues(int start, int num, \
358  const valueType *newValues); \
359  \
360  /* Set 1 value at given index */ \
361  void set1Value(int index, valueRef newValue); \
362  \
363  /* Set field to have one value */ \
364  void setValue(valueRef newValue); \
365  valueRef operator =(valueRef newValue) \
366  { setValue(newValue); return newValue; } \
367  \
368  /* Equality/inequality test for fields of same type */ \
369  bool operator ==(const className &f) const; \
370  bool operator !=(const className &f) const \
371  { return ! ((*this) == f); } \
372  \
373  /* Get non-const pointer into array of values for batch edits */ \
374  valueType * startEditing() \
375  { evaluate(); return values; } \
376  \
377  /* Indicate that batch edits have finished */ \
378  void finishEditing() { valueChanged(); } \
379  \
380  protected: \
381  /* Allocates room for num values. Copies old values (if any) into */ \
382  /* new area. Deletes old area, if any. Will reduce room if needed, */ \
383  /* so a value of newNum==0 will delete all values. */ \
384  virtual void allocValues(int newNum); \
385  \
386  /* Deletes all current values, resets number of values */ \
387  virtual void deleteAllValues(); \
388  \
389  /* Copies value indexed by "from" to value indexed by "to" */ \
390  virtual void copyValue(int to, int from); \
391  \
392  valueType *values
393 
401 
402 #define SO_MFIELD_DERIVED_VALUE_HEADER(className, valueType, valueRef) \
403  SO__MFIELD_RW_HEADER(className); \
404  public: \
405  /* Since = operator is not inherited, we redefine it here */ \
406  valueRef operator =(valueRef newValue) \
407  { setValue(newValue); return newValue; }
408 
415 
416 #define SO_MFIELD_HEADER(className, valueType, valueRef) \
417  SO_MFIELD_REQUIRED_HEADER(className); \
418  SO_MFIELD_CONSTRUCTOR_HEADER(className); \
419  SO_MFIELD_VALUE_HEADER(className, valueType, valueRef)
420 
428 
429 #define SO_MFIELD_DERIVED_HEADER(className, valueType, valueRef) \
430  SO_MFIELD_REQUIRED_HEADER(className); \
431  SO_MFIELD_CONSTRUCTOR_HEADER(className); \
432  SO_MFIELD_DERIVED_VALUE_HEADER(className, valueType, valueRef)
433 
440 
447 
448 #define SO_SFIELD_INIT_CLASS(className,parentClass) \
449  SO__FIELD_INIT_CLASS(className, SO__QUOTE(className), parentClass)
450 
457 
458 #define SO_SFIELD_REQUIRED_SOURCE(className) \
459  \
460  SO__FIELD_ID_SOURCE(className); \
461  SO__FIELD_EQ_SAME_SOURCE(className) \
462  \
463 const className & \
464 className::operator =(const className &f) \
465 { \
466  setValue(f.getValue()); \
467  return *this; \
468 }
469 
475 
476 #define SO_SFIELD_CONSTRUCTOR_SOURCE(className) \
477  \
478 className::className() \
479 { \
480 } \
481 className::~className() \
482 { \
483 }
484 
491 
492 #define SO_SFIELD_VALUE_SOURCE(className, valueType, valueRef) \
493  \
494 void \
495 className::setValue(valueRef newValue) \
496 { \
497  value = newValue; \
498  valueChanged(); \
499 } \
500  \
501 bool \
502 className::operator ==(const className &f) const \
503 { \
504  return getValue() == f.getValue(); \
505 }
506 
513 
514 #define SO_SFIELD_SOURCE(className, valueType, valueRef) \
515  SO_SFIELD_REQUIRED_SOURCE(className); \
516  SO_SFIELD_CONSTRUCTOR_SOURCE(className); \
517  SO_SFIELD_VALUE_SOURCE(className, valueType, valueRef)
518 
526 
527 #define SO_SFIELD_DERIVED_SOURCE(className, valueType, valueRef) \
528  SO_SFIELD_REQUIRED_SOURCE(className); \
529  SO_SFIELD_CONSTRUCTOR_SOURCE(className)
530 
537 
544 
545 #define SO_MFIELD_INIT_CLASS(className,parentClass) \
546  SO__FIELD_INIT_CLASS(className, SO__QUOTE(className), parentClass)
547 
554 
555 #define SO_MFIELD_REQUIRED_SOURCE(className) \
556  \
557  SO__FIELD_ID_SOURCE(className); \
558  SO__FIELD_EQ_SAME_SOURCE(className) \
559  \
560 const className & \
561 className::operator =(const className &f) \
562 { \
563  if (f.getNum() < getNum()) \
564  deleteAllValues(); \
565  setValues(0, f.getNum(), f.getValues(0)); \
566  return *this; \
567 }
568 
577 
578 #define SO_MFIELD_CONSTRUCTOR_SOURCE(className) \
579  \
580 className::className() \
581 { \
582  values = NULL; \
583 } \
584  \
585 className::~className() \
586 { \
587  deleteAllValues(); \
588 }
589 
597 
598 #define SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(className) \
599  \
600 className::className() \
601 { \
602 } \
603  \
604 className::~className() \
605 { \
606 }
607 
614 
615 #define SO_MFIELD_VALUE_SOURCE(className, valueType, valueRef) \
616  \
617 int \
618 className::find(valueRef targetValue, bool addIfNotFound) \
619 { \
620  int i, localNum = getNum(); \
621  \
622  for (i = 0; i < localNum; i++) \
623  if (values[i] == targetValue) \
624  return i; \
625  \
626  if (addIfNotFound) \
627  set1Value(localNum, targetValue); \
628  \
629  return -1; \
630 } \
631  \
632 void \
633 className::setValues(int start, int localNum, const valueType *newValues) \
634 { \
635  int newNum = start + localNum, i; \
636  \
637  if (newNum > getNum()) \
638  makeRoom(newNum); \
639  \
640  for (i = 0; i < localNum; i++) \
641  values[start + i] = newValues[i]; \
642  \
643  valueChanged(); \
644 } \
645  \
646 void \
647 className::set1Value(int index, valueRef newValue) \
648 { \
649  if (index >= getNum()) \
650  makeRoom(index + 1); \
651  values[index] = newValue; \
652  valueChanged(); \
653 } \
654  \
655 void \
656 className::setValue(valueRef newValue) \
657 { \
658  makeRoom(1); \
659  values[0] = newValue; \
660  valueChanged(); \
661 } \
662  \
663 bool \
664 className::operator ==(const className &f) const \
665 { \
666  int i, localNum = getNum(); \
667  const valueType *myVals, *itsVals; \
668  \
669  if (localNum != f.getNum()) \
670  return FALSE; \
671  \
672  myVals = getValues(0); \
673  itsVals = f.getValues(0); \
674  \
675  for (i = 0; i < localNum; i++) \
676  if (! (myVals[i] == itsVals[i])) \
677  return FALSE; \
678  \
679  return TRUE; \
680 } \
681  \
682 void \
683 className::deleteAllValues() \
684 { \
685  allocValues(0); \
686 } \
687  \
688 void \
689 className::copyValue(int to, int from) \
690 { \
691  values[to] = values[from]; \
692 }
693 
701 
702 #define SO_MFIELD_ALLOC_SOURCE(className, valueType) \
703 void \
704 className::allocValues(int newNum) \
705 { \
706  if (values == NULL) { \
707  if (newNum > 0) \
708  values = new valueType[newNum]; \
709  } \
710  else { \
711  valueType *oldValues = values; \
712  int i; \
713  \
714  if (newNum > 0) { \
715  values = new valueType[newNum]; \
716  for (i = 0; i < num && i < newNum; i++) \
717  values[i] = oldValues[i]; \
718  } \
719  else \
720  values = NULL; \
721  delete [] oldValues; \
722  } \
723  \
724  num = maxNum = newNum; \
725 }
726 
736 
737 #define SO_MFIELD_MALLOC_SOURCE(className, valueType) \
738 void \
739 className::allocValues(int newNum) \
740 { \
741  if (values == NULL) { \
742  if (newNum > 0) \
743  values = static_cast<valueType *>(malloc(sizeof(valueType) * newNum));\
744  } \
745  else { \
746  if (newNum > 0) \
747  values = static_cast<valueType *>(realloc(values, sizeof(valueType)*newNum));\
748  else { \
749  free(values); \
750  values = NULL; \
751  } \
752  } \
753  \
754  num = maxNum = newNum; \
755 }
756 
764 
765 #define SO_MFIELD_SOURCE(className, valueType, valueRef) \
766  SO_MFIELD_REQUIRED_SOURCE(className) \
767  SO_MFIELD_CONSTRUCTOR_SOURCE(className) \
768  SO_MFIELD_VALUE_SOURCE(className, valueType, valueRef) \
769  SO_MFIELD_ALLOC_SOURCE(className, valueType)
770 
777 
778 #define SO_MFIELD_SOURCE_MALLOC(className, valueType, valueRef) \
779  SO_MFIELD_REQUIRED_SOURCE(className) \
780  SO_MFIELD_CONSTRUCTOR_SOURCE(className) \
781  SO_MFIELD_VALUE_SOURCE(className, valueType, valueRef) \
782  SO_MFIELD_MALLOC_SOURCE(className, valueType)
783 
791 
792 #define SO_MFIELD_DERIVED_SOURCE(className, valueType, valueRef) \
793  SO_MFIELD_REQUIRED_SOURCE(className); \
794  SO_MFIELD_DERIVED_CONSTRUCTOR_SOURCE(className)
795 
796 
797 #endif /* _SO_SUB_FIELD_ */