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#include "ImfForward.h"
50#include "ImfExport.h"
51#include "ImfNamespace.h"
52
53OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
54
55
56class IMF_EXPORT Attribute
57{
58 public:
59
60 //---------------------------
61 // Constructor and destructor
62 //---------------------------
63
64 Attribute ();
65 virtual ~Attribute ();
66
67
68 //-------------------------------
69 // Get this attribute's type name
70 //-------------------------------
71
72 virtual const char * typeName () const = 0;
73
74
75 //------------------------------
76 // Make a copy of this attribute
77 //------------------------------
78
79 virtual Attribute * copy () const = 0;
80
81
82 //----------------------------------------
83 // Type-specific attribute I/O and copying
84 //----------------------------------------
85
86 virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
87 int version) const = 0;
88
89 virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
90 int size,
91 int version) = 0;
92
93 virtual void copyValueFrom (const Attribute &other) = 0;
94
95
96 //------------------
97 // Attribute factory
98 //------------------
99
100 static Attribute * newAttribute (const char typeName[]);
101
102
103 //-----------------------------------------------------------
104 // Test if a given attribute type has already been registered
105 //-----------------------------------------------------------
106
107 static bool knownType (const char typeName[]);
108
109
110 protected:
111
112 //--------------------------------------------------
113 // Register an attribute type so that newAttribute()
114 // knows how to make objects of this type.
115 //--------------------------------------------------
116
117 static void registerAttributeType (const char typeName[],
118 Attribute *(*newAttribute)());
119
120 //------------------------------------------------------
121 // Un-register an attribute type so that newAttribute()
122 // no longer knows how to make objects of this type (for
123 // debugging only).
124 //------------------------------------------------------
125
126 static void unRegisterAttributeType (const char typeName[]);
127};
128
129
130//-------------------------------------------------
131// Class template for attributes of a specific type
132//-------------------------------------------------
133
134template <class T>
135class TypedAttribute: public Attribute
136{
137 public:
138
139 //----------------------------
140 // Constructors and destructor
141 //------------_---------------
142
143 TypedAttribute ();
144 TypedAttribute (const T &value);
145 TypedAttribute (const TypedAttribute<T> &other);
146 virtual ~TypedAttribute ();
147
148
149 //--------------------------------
150 // Access to the attribute's value
151 //--------------------------------
152
153 T & value ();
154 const T & value () const;
155
156
157 //--------------------------------
158 // Get this attribute's type name.
159 //--------------------------------
160
161 virtual const char * typeName () const;
162
163
164 //---------------------------------------------------------
165 // Static version of typeName()
166 // This function must be specialized for each value type T.
167 //---------------------------------------------------------
168
169 static const char * staticTypeName ();
170
171
172 //---------------------
173 // Make a new attribute
174 //---------------------
175
176 static Attribute * makeNewAttribute ();
177
178
179 //------------------------------
180 // Make a copy of this attribute
181 //------------------------------
182
183 virtual Attribute * copy () const;
184
185
186 //-----------------------------------------------------------------
187 // Type-specific attribute I/O and copying.
188 // Depending on type T, these functions may have to be specialized.
189 //-----------------------------------------------------------------
190
191 virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
192 int version) const;
193
194 virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
195 int size,
196 int version);
197
198 virtual void copyValueFrom (const Attribute &other);
199
200
201 //------------------------------------------------------------
202 // Dynamic casts that throw exceptions instead of returning 0.
203 //------------------------------------------------------------
204
205 static TypedAttribute * cast (Attribute *attribute);
206 static const TypedAttribute * cast (const Attribute *attribute);
207 static TypedAttribute & cast (Attribute &attribute);
208 static const TypedAttribute & cast (const Attribute &attribute);
209
210
211 //---------------------------------------------------------------
212 // Register this attribute type so that Attribute::newAttribute()
213 // knows how to make objects of this type.
214 //
215 // Note that this function is not thread-safe because it modifies
216 // a global variable in the IlmIlm library. A thread in a multi-
217 // threaded program may call registerAttributeType() only when no
218 // other thread is accessing any functions or classes in the
219 // IlmImf library.
220 //
221 //---------------------------------------------------------------
222
223 static void registerAttributeType ();
224
225
226 //-----------------------------------------------------
227 // Un-register this attribute type (for debugging only)
228 //-----------------------------------------------------
229
230 static void unRegisterAttributeType ();
231
232
233 private:
234
235 T _value;
236};
237
238//------------------------------------
239// Implementation of TypedAttribute<T>
240//------------------------------------
241template <class T>
242TypedAttribute<T>::TypedAttribute ():
243 Attribute (),
244 _value (T())
245{
246 // empty
247}
248
249
250template <class T>
251TypedAttribute<T>::TypedAttribute (const T & value):
252 Attribute (),
253 _value (value)
254{
255 // empty
256}
257
258
259template <class T>
260TypedAttribute<T>::TypedAttribute (const TypedAttribute<T> &other):
261 Attribute (other),
262 _value ()
263{
264 copyValueFrom (other);
265}
266
267
268template <class T>
269TypedAttribute<T>::~TypedAttribute ()
270{
271 // empty
272}
273
274
275template <class T>
276inline T &
277TypedAttribute<T>::value ()
278{
279 return _value;
280}
281
282
283template <class T>
284inline const T &
285TypedAttribute<T>::value () const
286{
287 return _value;
288}
289
290
291template <class T>
292const char *
293TypedAttribute<T>::typeName () const
294{
295 return staticTypeName();
296}
297
298
299template <class T>
300Attribute *
301TypedAttribute<T>::makeNewAttribute ()
302{
303 return new TypedAttribute<T>();
304}
305
306
307template <class T>
308Attribute *
309TypedAttribute<T>::copy () const
310{
311 Attribute * attribute = new TypedAttribute<T>();
312 attribute->copyValueFrom (*this);
313 return attribute;
314}
315
316
317template <class T>
318void
319TypedAttribute<T>::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
320 int version) const
321{
322 OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, _value);
323}
324
325
326template <class T>
327void
328TypedAttribute<T>::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
329 int size,
330 int version)
331{
332 OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, _value);
333}
334
335
336template <class T>
337void
338TypedAttribute<T>::copyValueFrom (const Attribute &other)
339{
340 _value = cast(other)._value;
341}
342
343
344template <class T>
345TypedAttribute<T> *
346TypedAttribute<T>::cast (Attribute *attribute)
347{
348 TypedAttribute<T> *t =
349 dynamic_cast <TypedAttribute<T> *> (attribute);
350
351 if (t == 0)
352 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
353
354 return t;
355}
356
357
358template <class T>
359const TypedAttribute<T> *
360TypedAttribute<T>::cast (const Attribute *attribute)
361{
362 const TypedAttribute<T> *t =
363 dynamic_cast <const TypedAttribute<T> *> (attribute);
364
365 if (t == 0)
366 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
367
368 return t;
369}
370
371
372template <class T>
373inline TypedAttribute<T> &
374TypedAttribute<T>::cast (Attribute &attribute)
375{
376 return *cast (&attribute);
377}
378
379
380template <class T>
381inline const TypedAttribute<T> &
382TypedAttribute<T>::cast (const Attribute &attribute)
383{
384 return *cast (&attribute);
385}
386
387
388template <class T>
389inline void
390TypedAttribute<T>::registerAttributeType ()
391{
392 Attribute::registerAttributeType (staticTypeName(), makeNewAttribute);
393}
394
395
396template <class T>
397inline void
398TypedAttribute<T>::unRegisterAttributeType ()
399{
400 Attribute::unRegisterAttributeType (staticTypeName());
401}
402
403
404OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
405
406
407#endif
408