// ================================================================================================= // Copyright Adobe // Copyright 2010 Adobe // All Rights Reserved // // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= #include #include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header. #include "public/include/XMP_Const.h" #include "XMPFiles/source/FormatSupport/WAVE/Cr8rMetadata.h" #include "source/Endian.h" using namespace IFF_RIFF; static const XMP_Uns32 kCr8rSizeFix = 84; // always 84 bytes static const XMP_Uns32 kSizeFileExt = 16; static const XMP_Uns32 kSizeAppOtions = 16; static const XMP_Uns32 kSizeAppName = 32; // Needed to be able to memcpy directly to this struct. #if SUNOS_SPARC || SUNOS_X86 #pragma pack ( 1 ) #else #pragma pack ( push, 1 ) #endif //#if SUNOS_SPARC || SUNOS_X86 struct Cr8rBoxContent { XMP_Uns32 mMagic; XMP_Uns32 mSize; XMP_Uns16 mMajorVer; XMP_Uns16 mMinorVer; XMP_Uns32 mCreatorCode; XMP_Uns32 mAppleEvent; char mFileExt[kSizeFileExt]; char mAppOptions[kSizeAppOtions]; char mAppName[kSizeAppName]; }; #if SUNOS_SPARC || SUNOS_X86 #pragma pack ( ) #else #pragma pack ( pop ) #endif //#if SUNOS_SPARC || SUNOS_X86 //----------------------------------------------------------------------------- // // Cr8rMetadata::Cr8rMetadata(...) // // Purpose: ctor/dtor // //----------------------------------------------------------------------------- Cr8rMetadata::Cr8rMetadata() { } Cr8rMetadata::~Cr8rMetadata() { } //----------------------------------------------------------------------------- // // Cr8rMetadata::parse(...) // // Purpose: Parses the given memory block and creates a data model representation // The implementation expects that the memory block is the data area of // the BEXT chunk and its size is at least as big as the minimum size // of a BEXT data block. // Throws exceptions if parsing is not possible // //----------------------------------------------------------------------------- void Cr8rMetadata::parse( const XMP_Uns8* chunkData, XMP_Uns64 size ) { if( size >= kCr8rSizeFix ) { Cr8rBoxContent cr8r; memset( &cr8r, 0, kCr8rSizeFix ); // // copy input data into Cr8r block // Safe as fixed size matches size of struct that is #pragma packed(1) // memcpy( &cr8r, chunkData, kCr8rSizeFix ); // // copy values to map // this->setValue( kMagic, cr8r.mMagic ); this->setValue( kSize, cr8r.mSize ); this->setValue( kMajorVer, cr8r.mMajorVer ); this->setValue( kMinorVer, cr8r.mMinorVer ); this->setValue( kCreatorCode, cr8r.mCreatorCode ); this->setValue( kAppleEvent, cr8r.mAppleEvent ); this->setValue( kFileExt, std::string( cr8r.mFileExt, kSizeFileExt ) ); this->setValue( kAppOptions, std::string( cr8r.mAppOptions, kSizeAppOtions ) ); this->setValue( kAppName, std::string( cr8r.mAppName, kSizeAppName ) ); this->resetChanges(); } else { XMP_Throw ( "Not a valid Cr8r chunk", kXMPErr_BadFileFormat ); } } //----------------------------------------------------------------------------- // // Cr8rMetadata::serialize(...) // // Purpose: Serializes the data model to a memory block. // The memory block will be the data area of a BEXT chunk. // Throws exceptions if serializing is not possible // //----------------------------------------------------------------------------- XMP_Uns64 Cr8rMetadata::serialize( XMP_Uns8** outBuffer ) { XMP_Uns64 size = 0; if( outBuffer != NULL ) { const LittleEndian& LE = LittleEndian::getInstance(); size = kCr8rSizeFix; // // setup buffer // XMP_Uns8* buffer = new XMP_Uns8[static_cast(size)]; // // copy values and strings back to BEXT block // // ! Safe use of strncpy as the fixed size is consistent with the size of the destination buffer // But it is intentional here that the string might not be null terminated if // the size of the source is equal to the fixed size of the destination // Cr8rBoxContent cr8r; memset( &cr8r, 0, kCr8rSizeFix ); if( this->valueExists( kMagic ) ) { LE.putUns32( this->getValue( kMagic ), &cr8r.mMagic ); } if( this->valueExists( kSize ) ) { LE.putUns32( this->getValue( kSize ), &cr8r.mSize ); } if( this->valueExists( kMajorVer ) ) { LE.putUns16( this->getValue( kMajorVer ), &cr8r.mMajorVer ); } if( this->valueExists( kMinorVer ) ) { LE.putUns16( this->getValue( kMinorVer ), &cr8r.mMinorVer ); } if( this->valueExists( kCreatorCode ) ) { LE.putUns32( this->getValue( kCreatorCode ), &cr8r.mCreatorCode ); } if( this->valueExists( kAppleEvent ) ) { LE.putUns32( this->getValue( kAppleEvent ), &cr8r.mAppleEvent ); } if( this->valueExists( kFileExt ) ) { strncpy( cr8r.mFileExt, this->getValue( kFileExt ).c_str(), kSizeFileExt ); } if( this->valueExists( kAppOptions ) ) { strncpy( cr8r.mAppOptions, this->getValue( kAppOptions ).c_str(), kSizeAppOtions ); } if( this->valueExists( kAppName ) ) { strncpy( cr8r.mAppName, this->getValue( kAppName ).c_str(), kSizeAppName ); } // // set input buffer to zero // memset( buffer, 0, static_cast(size) ); // // copy Cr8r block into buffer // memcpy( buffer, &cr8r, kCr8rSizeFix ); *outBuffer = buffer; } else { XMP_Throw ( "Invalid buffer", kXMPErr_BadParam ); } return size; } //----------------------------------------------------------------------------- // // Cr8rMetadata::isEmptyValue(...) // // Purpose: Is the value of the passed ValueObject and its id "empty"? // //----------------------------------------------------------------------------- bool Cr8rMetadata::isEmptyValue( XMP_Uns32 id, ValueObject& valueObj ) { bool ret = true; switch( id ) { case kFileExt: case kAppOptions: case kAppName: { TValueObject* strObj = dynamic_cast*>(&valueObj); ret = ( strObj == NULL || ( strObj != NULL && strObj->getValue().empty() ) ); } break; case kMagic: case kSize: case kMajorVer: case kMinorVer: case kCreatorCode: case kAppleEvent: { ret = false; } break; default: { ret = true; } } return ret; }