337 lines
9.2 KiB
C
337 lines
9.2 KiB
C
|
//
|
||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||
|
// Copyright (c) Contributors to the OpenEXR Project.
|
||
|
//
|
||
|
|
||
|
#ifndef INCLUDED_IMF_ATTRIBUTE_H
|
||
|
#define INCLUDED_IMF_ATTRIBUTE_H
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//
|
||
|
// class Attribute
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include "ImfForward.h"
|
||
|
|
||
|
#include "ImfIO.h"
|
||
|
#include "ImfXdr.h"
|
||
|
|
||
|
#include "IexBaseExc.h"
|
||
|
|
||
|
#include <cstring>
|
||
|
#include <typeinfo>
|
||
|
|
||
|
#if defined(_MSC_VER)
|
||
|
// suppress warning about non-exported base classes
|
||
|
# pragma warning(push)
|
||
|
# pragma warning(disable : 4251)
|
||
|
# pragma warning(disable : 4275)
|
||
|
#endif
|
||
|
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
|
||
|
|
||
|
class IMF_EXPORT_TYPE Attribute
|
||
|
{
|
||
|
public:
|
||
|
//---------------------------
|
||
|
// Constructor and destructor
|
||
|
//---------------------------
|
||
|
|
||
|
IMF_EXPORT Attribute ();
|
||
|
IMF_EXPORT virtual ~Attribute ();
|
||
|
|
||
|
//-------------------------------
|
||
|
// Get this attribute's type name
|
||
|
//-------------------------------
|
||
|
|
||
|
virtual const char* typeName () const = 0;
|
||
|
|
||
|
//------------------------------
|
||
|
// Make a copy of this attribute
|
||
|
//------------------------------
|
||
|
|
||
|
virtual Attribute* copy () const = 0;
|
||
|
|
||
|
//----------------------------------------
|
||
|
// Type-specific attribute I/O and copying
|
||
|
//----------------------------------------
|
||
|
|
||
|
virtual void writeValueTo (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, int version) const = 0;
|
||
|
|
||
|
virtual void readValueFrom (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int size, int version) = 0;
|
||
|
|
||
|
virtual void copyValueFrom (const Attribute& other) = 0;
|
||
|
|
||
|
//------------------
|
||
|
// Attribute factory
|
||
|
//------------------
|
||
|
|
||
|
IMF_EXPORT static Attribute* newAttribute (const char typeName[]);
|
||
|
|
||
|
//-----------------------------------------------------------
|
||
|
// Test if a given attribute type has already been registered
|
||
|
//-----------------------------------------------------------
|
||
|
|
||
|
IMF_EXPORT static bool knownType (const char typeName[]);
|
||
|
|
||
|
protected:
|
||
|
//--------------------------------------------------
|
||
|
// Register an attribute type so that newAttribute()
|
||
|
// knows how to make objects of this type.
|
||
|
//--------------------------------------------------
|
||
|
IMF_EXPORT
|
||
|
static void registerAttributeType (
|
||
|
const char typeName[], Attribute* (*newAttribute) ());
|
||
|
|
||
|
//------------------------------------------------------
|
||
|
// Un-register an attribute type so that newAttribute()
|
||
|
// no longer knows how to make objects of this type (for
|
||
|
// debugging only).
|
||
|
//------------------------------------------------------
|
||
|
IMF_EXPORT
|
||
|
static void unRegisterAttributeType (const char typeName[]);
|
||
|
};
|
||
|
|
||
|
//-------------------------------------------------
|
||
|
// Class template for attributes of a specific type
|
||
|
//-------------------------------------------------
|
||
|
|
||
|
template <class T>
|
||
|
class IMF_EXPORT_TEMPLATE_TYPE TypedAttribute : public Attribute
|
||
|
{
|
||
|
public:
|
||
|
//------------------------------------------------------------
|
||
|
// Constructors and destructor: default behavior. This assumes
|
||
|
// that the type T is copyable/assignable/moveable.
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
TypedAttribute () = default;
|
||
|
TypedAttribute (const T& value);
|
||
|
TypedAttribute (const TypedAttribute<T>& other) = default;
|
||
|
TypedAttribute (TypedAttribute<T>&& other) = default;
|
||
|
//NB: if we use a default destructor, it wreaks havoc with where the vtable and such end up
|
||
|
//at least under mingw+windows, and since we are providing extern template instantiations
|
||
|
//this will be pretty trim and should reduce code bloat
|
||
|
virtual ~TypedAttribute ();
|
||
|
|
||
|
TypedAttribute& operator= (const TypedAttribute<T>& other) = default;
|
||
|
TypedAttribute& operator= (TypedAttribute<T>&& other) = default;
|
||
|
|
||
|
//--------------------------------
|
||
|
// Access to the attribute's value
|
||
|
//--------------------------------
|
||
|
|
||
|
T& value ();
|
||
|
const T& value () const;
|
||
|
|
||
|
//--------------------------------
|
||
|
// Get this attribute's type name.
|
||
|
//--------------------------------
|
||
|
|
||
|
virtual const char* typeName () const;
|
||
|
|
||
|
//---------------------------------------------------------
|
||
|
// Static version of typeName()
|
||
|
// This function must be specialized for each value type T.
|
||
|
//---------------------------------------------------------
|
||
|
|
||
|
static const char* staticTypeName ();
|
||
|
|
||
|
//---------------------
|
||
|
// Make a new attribute
|
||
|
//---------------------
|
||
|
|
||
|
static Attribute* makeNewAttribute ();
|
||
|
|
||
|
//------------------------------
|
||
|
// Make a copy of this attribute
|
||
|
//------------------------------
|
||
|
|
||
|
virtual Attribute* copy () const;
|
||
|
|
||
|
//-----------------------------------------------------------------
|
||
|
// Type-specific attribute I/O and copying.
|
||
|
// Depending on type T, these functions may have to be specialized.
|
||
|
//-----------------------------------------------------------------
|
||
|
|
||
|
virtual void writeValueTo (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, int version) const;
|
||
|
|
||
|
virtual void readValueFrom (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int size, int version);
|
||
|
|
||
|
virtual void copyValueFrom (const Attribute& other);
|
||
|
|
||
|
//------------------------------------------------------------
|
||
|
// Dynamic casts that throw exceptions instead of returning 0.
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
static TypedAttribute* cast (Attribute* attribute);
|
||
|
static const TypedAttribute* cast (const Attribute* attribute);
|
||
|
static TypedAttribute& cast (Attribute& attribute);
|
||
|
static const TypedAttribute& cast (const Attribute& attribute);
|
||
|
|
||
|
//---------------------------------------------------------------
|
||
|
// Register this attribute type so that Attribute::newAttribute()
|
||
|
// knows how to make objects of this type.
|
||
|
//
|
||
|
// Note that this function is not thread-safe because it modifies
|
||
|
// a global variable in the IlmIlm library. A thread in a multi-
|
||
|
// threaded program may call registerAttributeType() only when no
|
||
|
// other thread is accessing any functions or classes in the
|
||
|
// OpenEXR library.
|
||
|
//
|
||
|
//---------------------------------------------------------------
|
||
|
|
||
|
static void registerAttributeType ();
|
||
|
|
||
|
//-----------------------------------------------------
|
||
|
// Un-register this attribute type (for debugging only)
|
||
|
//-----------------------------------------------------
|
||
|
|
||
|
static void unRegisterAttributeType ();
|
||
|
|
||
|
private:
|
||
|
T _value;
|
||
|
};
|
||
|
|
||
|
//------------------------------------
|
||
|
// Implementation of TypedAttribute<T>
|
||
|
//------------------------------------
|
||
|
|
||
|
template <class T>
|
||
|
TypedAttribute<T>::TypedAttribute (const T& value)
|
||
|
: Attribute (), _value (value)
|
||
|
{
|
||
|
// empty
|
||
|
}
|
||
|
|
||
|
template <class T> TypedAttribute<T>::~TypedAttribute ()
|
||
|
{
|
||
|
// empty
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline T&
|
||
|
TypedAttribute<T>::value ()
|
||
|
{
|
||
|
return _value;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline const T&
|
||
|
TypedAttribute<T>::value () const
|
||
|
{
|
||
|
return _value;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
const char*
|
||
|
TypedAttribute<T>::typeName () const
|
||
|
{
|
||
|
return staticTypeName ();
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
Attribute*
|
||
|
TypedAttribute<T>::makeNewAttribute ()
|
||
|
{
|
||
|
return new TypedAttribute<T> ();
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
Attribute*
|
||
|
TypedAttribute<T>::copy () const
|
||
|
{
|
||
|
Attribute* attribute = new TypedAttribute<T> ();
|
||
|
attribute->copyValueFrom (*this);
|
||
|
return attribute;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
void
|
||
|
TypedAttribute<T>::writeValueTo (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, int version) const
|
||
|
{
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write<
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, _value);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
void
|
||
|
TypedAttribute<T>::readValueFrom (
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int size, int version)
|
||
|
{
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read<
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, _value);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
void
|
||
|
TypedAttribute<T>::copyValueFrom (const Attribute& other)
|
||
|
{
|
||
|
_value = cast (other)._value;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
TypedAttribute<T>*
|
||
|
TypedAttribute<T>::cast (Attribute* attribute)
|
||
|
{
|
||
|
TypedAttribute<T>* t = dynamic_cast<TypedAttribute<T>*> (attribute);
|
||
|
|
||
|
if (t == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
|
||
|
|
||
|
return t;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
const TypedAttribute<T>*
|
||
|
TypedAttribute<T>::cast (const Attribute* attribute)
|
||
|
{
|
||
|
const TypedAttribute<T>* t =
|
||
|
dynamic_cast<const TypedAttribute<T>*> (attribute);
|
||
|
|
||
|
if (t == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
|
||
|
|
||
|
return t;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline TypedAttribute<T>&
|
||
|
TypedAttribute<T>::cast (Attribute& attribute)
|
||
|
{
|
||
|
return *cast (&attribute);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline const TypedAttribute<T>&
|
||
|
TypedAttribute<T>::cast (const Attribute& attribute)
|
||
|
{
|
||
|
return *cast (&attribute);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline void
|
||
|
TypedAttribute<T>::registerAttributeType ()
|
||
|
{
|
||
|
Attribute::registerAttributeType (staticTypeName (), makeNewAttribute);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
inline void
|
||
|
TypedAttribute<T>::unRegisterAttributeType ()
|
||
|
{
|
||
|
Attribute::unRegisterAttributeType (staticTypeName ());
|
||
|
}
|
||
|
|
||
|
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
|
||
|
|
||
|
#if defined(_MSC_VER)
|
||
|
# pragma warning(pop)
|
||
|
#endif
|
||
|
|
||
|
#endif
|