1 #ifndef __XMPFiles_hpp__ 2 #define __XMPFiles_hpp__ 1 3 4 // ================================================================================================= 5 // ADOBE SYSTEMS INCORPORATED 6 // Copyright 2002-2007 Adobe Systems Incorporated 7 // All Rights Reserved 8 // 9 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 10 // of the Adobe license agreement accompanying it. 11 // ================================================================================================= 12 13 #include <string> 14 15 #define TXMP_STRING_TYPE std::string 16 #include "XMP.hpp" 17 18 #if XMP_UNIXBuild 19 typedef int LFA_FileRef; 20 #else 21 typedef void * LFA_FileRef; 22 #endif 23 24 class XMPFileHandler; 25 26 // ================================================================================================= 27 /// \file XMPFiles.hpp 28 /// \brief High level support to access metadata in files of interest to Adobe applications. 29 /// 30 /// This header ... 31 /// 32 // ================================================================================================= 33 34 // ================================================================================================= 35 // *** Usage Notes (eventually to become Doxygen comments) *** 36 // =========================================================== 37 // 38 // This is the main part of the internal (DLL side) implementation of XMPFiles. Other parts are 39 // the entry point wrappers and the file format handlers. The XMPFiles class distills the client 40 // API from TXMPFiles.hpp, removing convenience overloads and substituting a pointer/length pair 41 // for output strings. 42 // 43 // The wrapper functions provide a stable binary interface and perform minor impedance correction 44 // between the client template API from TDocMeta.hpp and the DLL's XMPFiles class. The details of 45 // the wrappers should be considered private. 46 // 47 // File handlers are registered during DLL initialization with hard coded calls in Init_XMPFiles. 48 // Each file handler provides 2 standalone functions, CheckFormatProc and DocMetaHandlerCTor, plus a 49 // class derived from DocMetaHandler. The format and capability flags are passed when registering. 50 // This allows the same physical handler to be registered for multiple formats. 51 // 52 // ------------------------------------------------------------------------------------------------- 53 // 54 // Basic outlines of the processing by the XMPFiles methods: 55 // 56 // Constructor: 57 // - Minimal work to create an empty XMPFiles object, set the ref count to 1. 58 // 59 // Destructor: 60 // - Decrement the ref count, return if greater than zero. 61 // - Call LFA_Close if necessary. 62 // 63 // UnlockLib & UnlockObj: 64 // - Release the thread lock. Same for now, no per-object lock. 65 // 66 // GetFormatInfo: 67 // - Return the flags for the registered handler. 68 // 69 // OpenFile: 70 // - The physical file is opened via LFA_OpenFile. 71 // - A handler is selected by calling the registered format checkers. 72 // - The handler object is created by calling the registered constructor proc. 73 // 74 // CloseFile: 75 // - Return if there is no open file (not an error). 76 // - If not a crash-safe update (includes read-only or no update), or the handler owns the file: 77 // - Throw an exception if the handler owns the file but does not support safe update. 78 // - If the file needs updating, call the handler's UpdateFile method. 79 // - else: 80 // - If the handler supports file rewrite: 81 // - *** This might not preserve ownership and permissions. 82 // - Create an empty temp file. 83 // - Call the handler's WriteFile method, writing to the temp file. 84 // - else 85 // - *** This preserves ownership, permissions, and Mac resources. 86 // - Copy the original file to a temp name (Mac data fork only). 87 // - Rename the original file to a different temp name. 88 // - Rename the copy file back to the original name. 89 // - Call the handler's UpdateFile method for the "original as temp" file. 90 // - Close both the original and temp files. 91 // - Delete the file with the original name. 92 // - Rename the temp file to the original name. 93 // - Delete the handler object. 94 // - Call LFA_Close if necessary. 95 // 96 // GetFileInfo: 97 // - Return the file info from the XMPFiles member variables. 98 // 99 // GetXMP: 100 // - Throw an exception if there is no open file. 101 // - Call the handler's GetXMP method. 102 // 103 // PutXMP: 104 // - Throw an exception if there is no open file. 105 // - Call the handler's PutXMP method. 106 // 107 // CanPutXMP: 108 // - Implement roughly as shown in TXMPFiles.hpp, there is no handler CanPutXMP method. 109 // 110 // ------------------------------------------------------------------------------------------------- 111 // 112 // The format checker should do nothing but the minimal work to identify the overall file format. 113 // In particular it should not look for XMP or other metadata. Note that the format checker has no 114 // means to carry state forward, it just returns a yes/no answer about a particular file format. 115 // 116 // The format checker and file handler should use the LFA_* functions for all I/O. They should not 117 // open or close the file themselves unless the handler sets the "handler-owns-file" flag. 118 // 119 // The format checker is passed the format being checked, allowing one checker to handle multiple 120 // formats. It is passed the LFA file ref so that it can do additional reads if necessary. The 121 // buffer is from the start of the file, the file will be positioned to the byte following the 122 // buffer. The buffer length will be at least 4K, unless the file is smaller in which case it will 123 // be the length of the file. This buffer may be reused for additional reads. 124 // 125 // Identifying some file formats can require checking variable length strings. Doing seeks and reads 126 // for each is suboptimal. There are utilities to maintain a rolling buffer and ensure that a given 127 // amount of data is available. See the template file handler code for details. 128 // 129 // ------------------------------------------------------------------------------------------------- 130 // 131 // The file handler has no explicit open and close methods. These are implicit in the handler's 132 // constructor and destructor. The file handler should use the XMPFiles member variables for the 133 // active file ref (and path if necessary), unless it owns the file. Note that these might change 134 // between the open and close in the case of crash-safe updates. Don't copy the XMPFiles member 135 // variables in the handler's constructor, save the pointer to the XMPFiles object and access 136 // directly as needed. 137 // 138 // The handler should have an UpdateFile method. This is called from XMPFiles::CloseFile if the 139 // file needs to be updated. The handler's destructor must only close the file, not update it. 140 // The handler can optionally have a WriteFile method, if it can rewrite the entire file. 141 // 142 // The handler is free to use its best judgement about caching parts of the file in memory. Overall 143 // speed of a single open/get/put/close cycle is probably the best goal, assuming a modern processor 144 // with a reasonable (significant but not enormous) amount of RAM. 145 // 146 // The handler methods will be called in a per-object thread safe manner. Concurrent access might 147 // occur for different objects, but not for the same object. The handler's constructor and destructor 148 // will always be globally serialized, so they can safely modify global data structures. 149 // 150 // (Testing issue: What about separate XMPFiles objects accessing the same file?) 151 // 152 // Handler's must not have any global objects that are heap allocated. Use pointers to objects that 153 // are allocated and deleted during the XMPFiles initialization and termination process. Some 154 // client apps are very picky about what they detect as memory leaks. 155 // 156 // static char gSomeBuffer [10*1000]; // OK, not from the heap. 157 // static std::string gSomeString; // Not OK, content from the heap. 158 // static std::vector<int> gSomeVector; // Not OK, content from the heap. 159 // static std::string * gSomeString = 0; // OK, alloc at init, delete at term. 160 // static std::vector<int> * gSomeVector = 0; // OK, alloc at init, delete at term. 161 // 162 // ================================================================================================= 163 164 class XMPFiles { 165 public: 166 167 static void GetVersionInfo ( XMP_VersionInfo * info ); 168 169 static bool Initialize ( XMP_OptionBits options = 0 ); 170 static void Terminate(); 171 172 XMPFiles(); 173 virtual ~XMPFiles(); 174 175 static void UnlockLib(); 176 void UnlockObj(); 177 178 static bool GetFormatInfo ( XMP_FileFormat format, 179 XMP_OptionBits * flags = 0 ); 180 181 static XMP_FileFormat CheckFileFormat ( XMP_StringPtr filePath ); 182 static XMP_FileFormat CheckPackageFormat ( XMP_StringPtr folderPath ); 183 184 bool OpenFile ( XMP_StringPtr filePath, 185 XMP_FileFormat format = kXMP_UnknownFile, 186 XMP_OptionBits openFlags = 0 ); 187 188 void CloseFile ( XMP_OptionBits closeFlags = 0 ); 189 190 bool GetFileInfo ( XMP_StringPtr * filePath = 0, 191 XMP_StringLen * filePathLen = 0, 192 XMP_OptionBits * openFlags = 0, 193 XMP_FileFormat * format = 0, 194 XMP_OptionBits * handlerFlags = 0 ); 195 196 void SetAbortProc ( XMP_AbortProc abortProc, 197 void * abortArg ); 198 199 bool GetXMP ( SXMPMeta * xmpObj = 0, 200 XMP_StringPtr * xmpPacket = 0, 201 XMP_StringLen * xmpPacketLen = 0, 202 XMP_PacketInfo * packetInfo = 0 ); 203 204 bool GetThumbnail ( XMP_ThumbnailInfo * tnailInfo ); 205 206 void PutXMP ( const SXMPMeta & xmpObj ); 207 208 void PutXMP ( XMP_StringPtr xmpPacket, 209 XMP_StringLen xmpPacketLen = kXMP_UseNullTermination ); 210 211 bool CanPutXMP ( const SXMPMeta & xmpObj ); 212 213 bool CanPutXMP ( XMP_StringPtr xmpPacket, 214 XMP_StringLen xmpPacketLen = kXMP_UseNullTermination ); 215 216 // Leave this data public so file handlers can see it. 217 218 XMP_Int32 clientRefs; // ! Must be signed to allow decrement from zero. 219 220 XMP_FileFormat format; 221 LFA_FileRef fileRef; // Non-zero if a file is open. 222 std::string filePath; 223 XMP_OptionBits openFlags; 224 XMPFileHandler * handler; // Non-null if a file is open. 225 void * handlerTemp; // For use between the CheckProc and handler creation. 226 227 XMP_AbortProc abortProc; 228 void * abortArg; 229 230 }; // XMPFiles 231 232 #endif /* __XMPFiles_hpp__ */ 233