1//
2// SPDX-License-Identifier: BSD-3-Clause
3// Copyright (c) Contributors to the OpenEXR Project.
4//
5
6
7#ifndef INCLUDED_IMF_ATTRIBUTE_H
8#define INCLUDED_IMF_ATTRIBUTE_H
9
10//-----------------------------------------------------------------------------
11//
12// class Attribute
13//
14//-----------------------------------------------------------------------------
15
16#include "ImfForward.h"
17
18#include "ImfIO.h"
19#include "ImfXdr.h"
20
21#include "IexBaseExc.h"
22
23#include <typeinfo>
24#include <cstring>
25
26
27#if defined(_MSC_VER)
28// suppress warning about non-exported base classes
29#pragma warning (push)
30#pragma warning (disable : 4251)
31#pragma warning (disable : 4275)
32#endif
33
34OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
35
36class IMF_EXPORT_TYPE Attribute
37{
38 public:
39
40 //---------------------------
41 // Constructor and destructor
42 //---------------------------
43
44 IMF_EXPORT Attribute ();
45 IMF_EXPORT virtual ~Attribute ();
46
47
48 //-------------------------------
49 // Get this attribute's type name
50 //-------------------------------
51
52 virtual const char * typeName () const = 0;
53
54
55 //------------------------------
56 // Make a copy of this attribute
57 //------------------------------
58
59 virtual Attribute * copy () const = 0;
60
61
62 //----------------------------------------
63 // Type-specific attribute I/O and copying
64 //----------------------------------------
65
66 virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
67 int version) const = 0;
68
69 virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
70 int size,
71 int version) = 0;
72
73 virtual void copyValueFrom (const Attribute &other) = 0;
74
75
76 //------------------
77 // Attribute factory
78 //------------------
79
80 IMF_EXPORT static Attribute * newAttribute (const char typeName[]);
81
82
83 //-----------------------------------------------------------
84 // Test if a given attribute type has already been registered
85 //-----------------------------------------------------------
86
87 IMF_EXPORT static bool knownType (const char typeName[]);
88
89 protected:
90
91 //--------------------------------------------------
92 // Register an attribute type so that newAttribute()
93 // knows how to make objects of this type.
94 //--------------------------------------------------
95 IMF_EXPORT
96 static void registerAttributeType (const char typeName[],
97 Attribute *(*newAttribute)());
98
99 //------------------------------------------------------
100 // Un-register an attribute type so that newAttribute()
101 // no longer knows how to make objects of this type (for
102 // debugging only).
103 //------------------------------------------------------
104 IMF_EXPORT
105 static void unRegisterAttributeType (const char typeName[]);
106};
107
108//-------------------------------------------------
109// Class template for attributes of a specific type
110//-------------------------------------------------
111
112template <class T>
113class IMF_EXPORT_TEMPLATE_TYPE TypedAttribute: public Attribute
114{
115 public:
116
117 //------------------------------------------------------------
118 // Constructors and destructor: default behavior. This assumes
119 // that the type T is copyable/assignable/moveable.
120 //------------------------------------------------------------
121
122 TypedAttribute () = default;
123 TypedAttribute (const T &value);
124 TypedAttribute (const TypedAttribute<T> &other) = default;
125 TypedAttribute (TypedAttribute<T> &&other) = default;
126 //NB: if we use a default destructor, it wreaks havoc with where the vtable and such end up
127 //at least under mingw+windows, and since we are providing extern template instantiations
128 //this will be pretty trim and should reduce code bloat
129 virtual ~TypedAttribute ();
130
131 TypedAttribute& operator = (const TypedAttribute<T>& other) = default;
132 TypedAttribute& operator = (TypedAttribute<T>&& other) = default;
133
134 //--------------------------------
135 // Access to the attribute's value
136 //--------------------------------
137
138 T & value ();
139 const T &value () const;
140
141
142 //--------------------------------
143 // Get this attribute's type name.
144 //--------------------------------
145
146 virtual const char * typeName () const;
147
148
149 //---------------------------------------------------------
150 // Static version of typeName()
151 // This function must be specialized for each value type T.
152 //---------------------------------------------------------
153
154 static const char * staticTypeName ();
155
156
157 //---------------------
158 // Make a new attribute
159 //---------------------
160
161 static Attribute * makeNewAttribute ();
162
163
164 //------------------------------
165 // Make a copy of this attribute
166 //------------------------------
167
168 virtual Attribute * copy () const;
169
170
171 //-----------------------------------------------------------------
172 // Type-specific attribute I/O and copying.
173 // Depending on type T, these functions may have to be specialized.
174 //-----------------------------------------------------------------
175
176 virtual void writeValueTo (
177 OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
178 int version) const;
179
180 virtual void readValueFrom (
181 OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
182 int size,
183 int version);
184
185 virtual void copyValueFrom (const Attribute &other);
186
187
188 //------------------------------------------------------------
189 // Dynamic casts that throw exceptions instead of returning 0.
190 //------------------------------------------------------------
191
192 static TypedAttribute * cast (Attribute *attribute);
193 static const TypedAttribute * cast (const Attribute *attribute);
194 static TypedAttribute & cast (Attribute &attribute);
195 static const TypedAttribute & cast (const Attribute &attribute);
196
197
198 //---------------------------------------------------------------
199 // Register this attribute type so that Attribute::newAttribute()
200 // knows how to make objects of this type.
201 //
202 // Note that this function is not thread-safe because it modifies
203 // a global variable in the IlmIlm library. A thread in a multi-
204 // threaded program may call registerAttributeType() only when no
205 // other thread is accessing any functions or classes in the
206 // OpenEXR library.
207 //
208 //---------------------------------------------------------------
209
210 static void registerAttributeType ();
211
212
213 //-----------------------------------------------------
214 // Un-register this attribute type (for debugging only)
215 //-----------------------------------------------------
216
217 static void unRegisterAttributeType ();
218
219
220 private:
221
222 T _value;
223};
224
225//------------------------------------
226// Implementation of TypedAttribute<T>
227//------------------------------------
228
229template <class T>
230TypedAttribute<T>::TypedAttribute (const T & value):
231 Attribute (),
232 _value (value)
233{
234 // empty
235}
236
237template <class T>
238TypedAttribute<T>::~TypedAttribute ()
239{
240 // empty
241}
242
243template <class T>
244inline T &
245TypedAttribute<T>::value ()
246{
247 return _value;
248}
249
250
251template <class T>
252inline const T &
253TypedAttribute<T>::value () const
254{
255 return _value;
256}
257
258
259template <class T>
260const char *
261TypedAttribute<T>::typeName () const
262{
263 return staticTypeName();
264}
265
266
267template <class T>
268Attribute *
269TypedAttribute<T>::makeNewAttribute ()
270{
271 return new TypedAttribute<T>();
272}
273
274
275template <class T>
276Attribute *
277TypedAttribute<T>::copy () const
278{
279 Attribute * attribute = new TypedAttribute<T>();
280 attribute->copyValueFrom (other: *this);
281 return attribute;
282}
283
284
285template <class T>
286void
287TypedAttribute<T>::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
288 int version) const
289{
290 OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, _value);
291}
292
293
294template <class T>
295void
296TypedAttribute<T>::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
297 int size,
298 int version)
299{
300 OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, _value);
301}
302
303
304template <class T>
305void
306TypedAttribute<T>::copyValueFrom (const Attribute &other)
307{
308 _value = cast(other)._value;
309}
310
311
312template <class T>
313TypedAttribute<T> *
314TypedAttribute<T>::cast (Attribute *attribute)
315{
316 TypedAttribute<T> *t =
317 dynamic_cast <TypedAttribute<T> *> (attribute);
318
319 if (t == 0)
320 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
321
322 return t;
323}
324
325
326template <class T>
327const TypedAttribute<T> *
328TypedAttribute<T>::cast (const Attribute *attribute)
329{
330 const TypedAttribute<T> *t =
331 dynamic_cast <const TypedAttribute<T> *> (attribute);
332
333 if (t == 0)
334 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
335
336 return t;
337}
338
339
340template <class T>
341inline TypedAttribute<T> &
342TypedAttribute<T>::cast (Attribute &attribute)
343{
344 return *cast (&attribute);
345}
346
347
348template <class T>
349inline const TypedAttribute<T> &
350TypedAttribute<T>::cast (const Attribute &attribute)
351{
352 return *cast (&attribute);
353}
354
355
356template <class T>
357inline void
358TypedAttribute<T>::registerAttributeType ()
359{
360 Attribute::registerAttributeType (typeName: staticTypeName(), newAttribute: makeNewAttribute);
361}
362
363
364template <class T>
365inline void
366TypedAttribute<T>::unRegisterAttributeType ()
367{
368 Attribute::unRegisterAttributeType (typeName: staticTypeName());
369}
370
371
372OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
373
374
375#if defined(_MSC_VER)
376#pragma warning (pop)
377#endif
378
379#endif
380

source code of include/OpenEXR/ImfAttribute.h