1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4// Digital Ltd. LLC
5//
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// *       Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// *       Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17// *       Neither the name of Industrial Light & Magic nor the names of
18// its contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33///////////////////////////////////////////////////////////////////////////
34
35
36
37#ifndef INCLUDED_IMF_ATTRIBUTE_H
38#define INCLUDED_IMF_ATTRIBUTE_H
39
40//-----------------------------------------------------------------------------
41//
42//	class Attribute
43//
44//-----------------------------------------------------------------------------
45
46#include "IexBaseExc.h"
47#include <ImfIO.h>
48#include <ImfXdr.h>
49
50
51namespace Imf {
52
53
54class Attribute
55{
56  public:
57
58    //---------------------------
59    // Constructor and destructor
60    //---------------------------
61
62    Attribute ();
63    virtual ~Attribute ();
64
65
66    //-------------------------------
67    // Get this attribute's type name
68    //-------------------------------
69
70    virtual const char *	typeName () const = 0;
71
72
73    //------------------------------
74    // Make a copy of this attribute
75    //------------------------------
76
77    virtual Attribute *		copy () const = 0;
78
79
80    //----------------------------------------
81    // Type-specific attribute I/O and copying
82    //----------------------------------------
83
84    virtual void		writeValueTo (OStream &os,
85					      int version) const = 0;
86
87    virtual void		readValueFrom (IStream &is,
88					       int size,
89					       int version) = 0;
90
91    virtual void		copyValueFrom (const Attribute &other) = 0;
92
93
94    //------------------
95    // Attribute factory
96    //------------------
97
98    static Attribute *		newAttribute (const char typeName[]);
99
100
101    //-----------------------------------------------------------
102    // Test if a given attribute type has already been registered
103    //-----------------------------------------------------------
104
105    static bool			knownType (const char typeName[]);
106
107
108  protected:
109
110    //--------------------------------------------------
111    // Register an attribute type so that newAttribute()
112    // knows how to make objects of this type.
113    //--------------------------------------------------
114
115    static void		registerAttributeType (const char typeName[],
116					       Attribute *(*newAttribute)());
117
118    //------------------------------------------------------
119    // Un-register an attribute type so that newAttribute()
120    // no longer knows how to make objects of this type (for
121    // debugging only).
122    //------------------------------------------------------
123
124    static void		unRegisterAttributeType (const char typeName[]);
125};
126
127
128//-------------------------------------------------
129// Class template for attributes of a specific type
130//-------------------------------------------------
131
132template <class T>
133class TypedAttribute: public Attribute
134{
135  public:
136
137    //----------------------------
138    // Constructors and destructor
139    //------------_---------------
140
141    TypedAttribute ();
142    TypedAttribute (const T &value);
143    TypedAttribute (const TypedAttribute<T> &other);
144    virtual ~TypedAttribute ();
145
146
147    //--------------------------------
148    // Access to the attribute's value
149    //--------------------------------
150
151    T &					value ();
152    const T &				value () const;
153
154
155    //--------------------------------
156    // Get this attribute's type name.
157    //--------------------------------
158
159    virtual const char *		typeName () const;
160
161
162    //---------------------------------------------------------
163    // Static version of typeName()
164    // This function must be specialized for each value type T.
165    //---------------------------------------------------------
166
167    static const char *			staticTypeName ();
168
169
170    //---------------------
171    // Make a new attribute
172    //---------------------
173
174    static Attribute *			makeNewAttribute ();
175
176
177    //------------------------------
178    // Make a copy of this attribute
179    //------------------------------
180
181    virtual Attribute *			copy () const;
182
183
184    //-----------------------------------------------------------------
185    // Type-specific attribute I/O and copying.
186    // Depending on type T, these functions may have to be specialized.
187    //-----------------------------------------------------------------
188
189    virtual void		writeValueTo (OStream &os,
190					      int version) const;
191
192    virtual void		readValueFrom (IStream &is,
193					       int size,
194					       int version);
195
196    virtual void		copyValueFrom (const Attribute &other);
197
198
199    //------------------------------------------------------------
200    // Dynamic casts that throw exceptions instead of returning 0.
201    //------------------------------------------------------------
202
203    static TypedAttribute *		cast (Attribute *attribute);
204    static const TypedAttribute *	cast (const Attribute *attribute);
205    static TypedAttribute &		cast (Attribute &attribute);
206    static const TypedAttribute &	cast (const Attribute &attribute);
207
208
209    //---------------------------------------------------------------
210    // Register this attribute type so that Attribute::newAttribute()
211    // knows how to make objects of this type.
212    //
213    // Note that this function is not thread-safe because it modifies
214    // a global variable in the IlmIlm library.  A thread in a multi-
215    // threaded program may call registerAttributeType() only when no
216    // other thread is accessing any functions or classes in the
217    // IlmImf library.
218    //
219    //---------------------------------------------------------------
220
221    static void				registerAttributeType ();
222
223
224    //-----------------------------------------------------
225    // Un-register this attribute type (for debugging only)
226    //-----------------------------------------------------
227
228    static void				 unRegisterAttributeType ();
229
230
231  private:
232
233    T					_value;
234};
235
236
237//------------------------------------
238// Implementation of TypedAttribute<T>
239//------------------------------------
240
241template <class T>
242TypedAttribute<T>::TypedAttribute (): _value (T())
243{
244    // empty
245}
246
247
248template <class T>
249TypedAttribute<T>::TypedAttribute (const T &value): _value (value)
250{
251    // empty
252}
253
254
255template <class T>
256TypedAttribute<T>::TypedAttribute (const TypedAttribute<T> &other):
257    _value ()
258{
259    copyValueFrom (other);
260}
261
262
263template <class T>
264TypedAttribute<T>::~TypedAttribute ()
265{
266    // empty
267}
268
269
270template <class T>
271inline T &
272TypedAttribute<T>::value ()
273{
274    return _value;
275}
276
277
278template <class T>
279inline const T &
280TypedAttribute<T>::value () const
281{
282    return _value;
283}
284
285
286template <class T>
287const char *
288TypedAttribute<T>::typeName () const
289{
290    return staticTypeName();
291}
292
293
294template <class T>
295Attribute *
296TypedAttribute<T>::makeNewAttribute ()
297{
298    return new TypedAttribute<T>();
299}
300
301
302template <class T>
303Attribute *
304TypedAttribute<T>::copy () const
305{
306    Attribute * attribute = new TypedAttribute<T>();
307    attribute->copyValueFrom (*this);
308    return attribute;
309}
310
311
312template <class T>
313void
314TypedAttribute<T>::writeValueTo (OStream &os, int version) const
315{
316    Xdr::write <StreamIO> (os, _value);
317}
318
319
320template <class T>
321void
322TypedAttribute<T>::readValueFrom (IStream &is, int size, int version)
323{
324    Xdr::read <StreamIO> (is, _value);
325}
326
327
328template <class T>
329void
330TypedAttribute<T>::copyValueFrom (const Attribute &other)
331{
332    _value = cast(other)._value;
333}
334
335
336template <class T>
337TypedAttribute<T> *
338TypedAttribute<T>::cast (Attribute *attribute)
339{
340    TypedAttribute<T> *t =
341	dynamic_cast <TypedAttribute<T> *> (attribute);
342
343    if (t == 0)
344	throw Iex::TypeExc ("Unexpected attribute type.");
345
346    return t;
347}
348
349
350template <class T>
351const TypedAttribute<T> *
352TypedAttribute<T>::cast (const Attribute *attribute)
353{
354    const TypedAttribute<T> *t =
355	dynamic_cast <const TypedAttribute<T> *> (attribute);
356
357    if (t == 0)
358	throw Iex::TypeExc ("Unexpected attribute type.");
359
360    return t;
361}
362
363
364template <class T>
365inline TypedAttribute<T> &
366TypedAttribute<T>::cast (Attribute &attribute)
367{
368    return *cast (&attribute);
369}
370
371
372template <class T>
373inline const TypedAttribute<T> &
374TypedAttribute<T>::cast (const Attribute &attribute)
375{
376    return *cast (&attribute);
377}
378
379
380template <class T>
381inline void
382TypedAttribute<T>::registerAttributeType ()
383{
384    Attribute::registerAttributeType (staticTypeName(), makeNewAttribute);
385}
386
387
388template <class T>
389inline void
390TypedAttribute<T>::unRegisterAttributeType ()
391{
392    Attribute::unRegisterAttributeType (staticTypeName());
393}
394
395
396} // namespace Imf
397
398#if defined(OPENEXR_DLL) && defined(_MSC_VER)
399    // Tell MS VC++ to disable "non dll-interface class used as base
400    // for dll-interface class" and "no suitable definition provided
401    // for explicit template"
402    #pragma warning (disable : 4275 4661)
403
404    #if defined (ILMIMF_EXPORTS)
405 	#define IMF_EXPIMP_TEMPLATE
406    #else
407 	#define IMF_EXPIMP_TEMPLATE extern
408    #endif
409
410    IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute<float>;
411    IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute<double>;
412
413    #pragma warning(default : 4251)
414    #undef EXTERN_TEMPLATE
415#endif
416
417// Metrowerks compiler wants the .cpp file inlined, too
418#ifdef __MWERKS__
419#include <ImfAttribute.cpp>
420#endif
421
422#endif
423