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