// // 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 #include #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 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& other) = default; TypedAttribute (TypedAttribute&& 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& other) = default; TypedAttribute& operator= (TypedAttribute&& 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 //------------------------------------ template TypedAttribute::TypedAttribute (const T& value) : Attribute (), _value (value) { // empty } template TypedAttribute::~TypedAttribute () { // empty } template inline T& TypedAttribute::value () { return _value; } template inline const T& TypedAttribute::value () const { return _value; } template const char* TypedAttribute::typeName () const { return staticTypeName (); } template Attribute* TypedAttribute::makeNewAttribute () { return new TypedAttribute (); } template Attribute* TypedAttribute::copy () const { Attribute* attribute = new TypedAttribute (); attribute->copyValueFrom (*this); return attribute; } template void TypedAttribute::writeValueTo ( OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, int version) const { OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write< OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, _value); } template void TypedAttribute::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 void TypedAttribute::copyValueFrom (const Attribute& other) { _value = cast (other)._value; } template TypedAttribute* TypedAttribute::cast (Attribute* attribute) { TypedAttribute* t = dynamic_cast*> (attribute); if (t == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return t; } template const TypedAttribute* TypedAttribute::cast (const Attribute* attribute) { const TypedAttribute* t = dynamic_cast*> (attribute); if (t == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return t; } template inline TypedAttribute& TypedAttribute::cast (Attribute& attribute) { return *cast (&attribute); } template inline const TypedAttribute& TypedAttribute::cast (const Attribute& attribute) { return *cast (&attribute); } template inline void TypedAttribute::registerAttributeType () { Attribute::registerAttributeType (staticTypeName (), makeNewAttribute); } template inline void TypedAttribute::unRegisterAttributeType () { Attribute::unRegisterAttributeType (staticTypeName ()); } OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #if defined(_MSC_VER) # pragma warning(pop) #endif #endif