diff options
Diffstat (limited to 'XMPFiles/source/XMPFiles.hpp')
-rw-r--r-- | XMPFiles/source/XMPFiles.hpp | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/XMPFiles/source/XMPFiles.hpp b/XMPFiles/source/XMPFiles.hpp new file mode 100644 index 0000000..f4f2e96 --- /dev/null +++ b/XMPFiles/source/XMPFiles.hpp @@ -0,0 +1,252 @@ +#ifndef __XMPFiles_hpp__ +#define __XMPFiles_hpp__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2004 Adobe Systems Incorporated +// 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 "public/include/XMP_Environment.h" // ! This must be the first include. + +#include <string> +#define TXMP_STRING_TYPE std::string +#include "public/include/XMP.hpp" + +#include "public/include/XMP_IO.hpp" + +class XMPFileHandler; +namespace Common{ struct XMPFileHandlerInfo; } + +// ================================================================================================= +/// \file XMPFiles.hpp +/// \brief High level support to access metadata in files of interest to Adobe applications. +/// +/// This header ... +/// +// ================================================================================================= + +// ================================================================================================= +// *** Usage Notes (eventually to become Doxygen comments) *** +// =========================================================== +// +// This is the main part of the internal (DLL side) implementation of XMPFiles. Other parts are +// the entry point wrappers and the file format handlers. The XMPFiles class distills the client +// API from TXMPFiles.hpp, removing convenience overloads and substituting a pointer/length pair +// for output strings. +// +// The wrapper functions provide a stable binary interface and perform minor impedance correction +// between the client template API from TDocMeta.hpp and the DLL's XMPFiles class. The details of +// the wrappers should be considered private. +// +// File handlers are registered during DLL initialization with hard coded calls in Init_XMPFiles. +// Each file handler provides 2 standalone functions, CheckFormatProc and DocMetaHandlerCTor, plus a +// class derived from DocMetaHandler. The format and capability flags are passed when registering. +// This allows the same physical handler to be registered for multiple formats. +// +// ------------------------------------------------------------------------------------------------- +// +// Basic outlines of the processing by the XMPFiles methods: +// +// Constructor: +// - Minimal work to create an empty XMPFiles object, set the ref count to 1. +// +// Destructor: +// - Decrement the ref count, return if greater than zero. +// - Call LFA_Close if necessary. +// +// UnlockLib & UnlockObj: +// - Release the thread lock. Same for now, no per-object lock. +// +// GetFormatInfo: +// - Return the flags for the registered handler. +// +// OpenFile: +// - The physical file is opened via LFA_OpenFile. +// - A handler is selected by calling the registered format checkers. +// - The handler object is created by calling the registered constructor proc. +// +// CloseFile: +// - Return if there is no open file (not an error). +// - If not a crash-safe update (includes read-only or no update), or the handler owns the file: +// - Throw an exception if the handler owns the file but does not support safe update. +// - If the file needs updating, call the handler's UpdateFile method. +// - else: +// - If the handler supports file rewrite: +// - *** This might not preserve ownership and permissions. +// - Create an empty temp file. +// - Call the handler's WriteFile method, writing to the temp file. +// - else +// - *** This preserves ownership, permissions, and Mac resources. +// - Copy the original file to a temp name (Mac data fork only). +// - Rename the original file to a different temp name. +// - Rename the copy file back to the original name. +// - Call the handler's UpdateFile method for the "original as temp" file. +// - Close both the original and temp files. +// - Delete the file with the original name. +// - Rename the temp file to the original name. +// - Delete the handler object. +// - Call LFA_Close if necessary. +// +// GetFileInfo: +// - Return the file info from the XMPFiles member variables. +// +// GetXMP: +// - Throw an exception if there is no open file. +// - Call the handler's GetXMP method. +// +// PutXMP: +// - Throw an exception if there is no open file. +// - Call the handler's PutXMP method. +// +// CanPutXMP: +// - Implement roughly as shown in TXMPFiles.hpp, there is no handler CanPutXMP method. +// +// ------------------------------------------------------------------------------------------------- +// +// The format checker should do nothing but the minimal work to identify the overall file format. +// In particular it should not look for XMP or other metadata. Note that the format checker has no +// means to carry state forward, it just returns a yes/no answer about a particular file format. +// +// The format checker and file handler should use the LFA_* functions for all I/O. They should not +// open or close the file themselves unless the handler sets the "handler-owns-file" flag. +// +// The format checker is passed the format being checked, allowing one checker to handle multiple +// formats. It is passed the LFA file ref so that it can do additional reads if necessary. The +// buffer is from the start of the file, the file will be positioned to the byte following the +// buffer. The buffer length will be at least 4K, unless the file is smaller in which case it will +// be the length of the file. This buffer may be reused for additional reads. +// +// Identifying some file formats can require checking variable length strings. Doing seeks and reads +// for each is suboptimal. There are utilities to maintain a rolling buffer and ensure that a given +// amount of data is available. See the template file handler code for details. +// +// ------------------------------------------------------------------------------------------------- +// +// The file handler has no explicit open and close methods. These are implicit in the handler's +// constructor and destructor. The file handler should use the XMPFiles member variables for the +// active file ref (and path if necessary), unless it owns the file. Note that these might change +// between the open and close in the case of crash-safe updates. Don't copy the XMPFiles member +// variables in the handler's constructor, save the pointer to the XMPFiles object and access +// directly as needed. +// +// The handler should have an UpdateFile method. This is called from XMPFiles::CloseFile if the +// file needs to be updated. The handler's destructor must only close the file, not update it. +// The handler can optionally have a WriteFile method, if it can rewrite the entire file. +// +// The handler is free to use its best judgement about caching parts of the file in memory. Overall +// speed of a single open/get/put/close cycle is probably the best goal, assuming a modern processor +// with a reasonable (significant but not enormous) amount of RAM. +// +// The handler methods will be called in a per-object thread safe manner. Concurrent access might +// occur for different objects, but not for the same object. The handler's constructor and destructor +// will always be globally serialized, so they can safely modify global data structures. +// +// (Testing issue: What about separate XMPFiles objects accessing the same file?) +// +// Handler's must not have any global objects that are heap allocated. Use pointers to objects that +// are allocated and deleted during the XMPFiles initialization and termination process. Some +// client apps are very picky about what they detect as memory leaks. +// +// static char gSomeBuffer [10*1000]; // OK, not from the heap. +// static std::string gSomeString; // Not OK, content from the heap. +// static std::vector<int> gSomeVector; // Not OK, content from the heap. +// static std::string * gSomeString = 0; // OK, alloc at init, delete at term. +// static std::vector<int> * gSomeVector = 0; // OK, alloc at init, delete at term. +// +// ================================================================================================= + +class XMPFiles { +public: + + static void GetVersionInfo ( XMP_VersionInfo * info ); + + static bool Initialize ( XMP_OptionBits options, const char* pluginFolder, const char* plugins = NULL ); + static void Terminate(); + + XMPFiles(); + virtual ~XMPFiles(); + + static bool GetFormatInfo ( XMP_FileFormat format, + XMP_OptionBits * flags = 0 ); + + static XMP_FileFormat CheckFileFormat ( XMP_StringPtr filePath ); + static XMP_FileFormat CheckPackageFormat ( XMP_StringPtr folderPath ); + + static bool GetFileModDate ( XMP_StringPtr filePath, + XMP_DateTime * modDate, + XMP_FileFormat * format = 0, // ! Can be null. + XMP_OptionBits options = 0 ); + + bool OpenFile ( XMP_StringPtr filePath, + XMP_FileFormat format = kXMP_UnknownFile, + XMP_OptionBits openFlags = 0 ); + + #if XMP_StaticBuild // ! Client XMP_IO objects can only be used in static builds. + bool OpenFile ( XMP_IO * clientIO, + XMP_FileFormat format = kXMP_UnknownFile, + XMP_OptionBits openFlags = 0 ); + #endif + + bool OpenFile( const Common::XMPFileHandlerInfo& hdlInfo, + XMP_StringPtr filePath, + XMP_OptionBits openFlags = 0 ); + +#if XMP_StaticBuild // ! Client XMP_IO objects can only be used in static builds. + bool OpenFile( const Common::XMPFileHandlerInfo& hdlInfo, + XMP_IO* clientIO, + XMP_OptionBits openFlags = 0 ); +#endif + + void CloseFile ( XMP_OptionBits closeFlags = 0 ); + + bool GetFileInfo ( XMP_StringPtr * filePath = 0, + XMP_StringLen * filePathLen = 0, + XMP_OptionBits * openFlags = 0, + XMP_FileFormat * format = 0, + XMP_OptionBits * handlerFlags = 0 ) const; + + void SetAbortProc ( XMP_AbortProc abortProc, + void * abortArg ); + + bool GetXMP ( SXMPMeta * xmpObj = 0, + XMP_StringPtr * xmpPacket = 0, + XMP_StringLen * xmpPacketLen = 0, + XMP_PacketInfo * packetInfo = 0 ); + + void PutXMP ( const SXMPMeta & xmpObj ); + + void PutXMP ( XMP_StringPtr xmpPacket, + XMP_StringLen xmpPacketLen = kXMP_UseNullTermination ); + + bool CanPutXMP ( const SXMPMeta & xmpObj ); + + bool CanPutXMP ( XMP_StringPtr xmpPacket, + XMP_StringLen xmpPacketLen = kXMP_UseNullTermination ); + + inline bool UsesClientIO() { return this->filePath.empty(); }; + inline bool UsesLocalIO() { return ( ! this->UsesClientIO() ); }; + + // Leave this data public so file handlers can see it. + + XMP_Int32 clientRefs; // ! Must be signed to allow decrement from zero. + XMP_ReadWriteLock lock; + + XMP_FileFormat format; + XMP_IO * ioRef; // Non-zero if a file is open. + std::string filePath; // Empty for client-managed I/O. + XMP_OptionBits openFlags; + XMPFileHandler * handler; // Non-null if a file is open. + + void * tempPtr; // For use between the CheckProc and handler creation. + XMP_Uns32 tempUI32; + + XMP_AbortProc abortProc; + void * abortArg; + +}; // XMPFiles + +#endif /* __XMPFiles_hpp__ */ |