1 #ifndef __Host_IO_hpp__ 2 #define __Host_IO_hpp__ 1 3 4 // ================================================================================================= 5 // Copyright 2010 Adobe Systems Incorporated 6 // All Rights Reserved. 7 // 8 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 9 // of the Adobe license agreement accompanying it. 10 // ================================================================================================= 11 12 #include "public/include/XMP_Environment.h" // ! This must be the first include. 13 14 #include "public/include/XMP_Const.h" 15 #include "public/include/XMP_IO.hpp" 16 17 #include <string> 18 19 #if XMP_WinBuild 20 #include <Windows.h> 21 #elif XMP_MacBuild 22 #include <CoreServices/CoreServices.h> 23 #include <dirent.h> // Mac uses the POSIX folder functions. 24 #elif XMP_UNIXBuild | XMP_iOSBuild 25 #include <dirent.h> 26 #else 27 #error "Unknown host platform." 28 #endif 29 30 // ================================================================================================= 31 // Host_IO is a collection of minimal convenient wrappers for host I/O services. It is intentionally 32 // a namespace and not a class. No state is kept here, these are just wrappers that provide a common 33 // internal API for basic I/O services that differ from host to host. 34 35 namespace Host_IO { 36 37 // ============================================================================================= 38 // File operations 39 // =============== 40 // 41 // ! The file operations should only be used in the implementation of XMPFiles_IO. 42 // 43 // Exists - Returns true if the path exists, whether as a file, folder, or anything else. Never 44 // throws an exception. 45 // 46 // Writable - Returns true 47 // a. In case checkCreationPossible is false check for existence and writable permissions. 48 // b. In case checkCreationPossible is true and path is not existence, check permissions of parent folder. 49 // 50 // Create - Create a file if possible, return true if successful. Return false if the file 51 // already exists. Throw an XMP_Error exception if the file cannot be created or if the path 52 // already exists but is not a file. 53 // 54 // GetModifyDate - Return the file system modification date. Returns false if the file or folder 55 // does not exist. 56 // 57 // CreateTemp - Create a (presumably) temporary file related to some other file. The source 58 // file path is passed in, a derived name is selected in the same folder. The source file need 59 // not exist, but all folders in the path must exist. The derived name is guaranteed to not 60 // already exist. A limited number of attempts are made to select a derived name. Returns the 61 // temporary file path if successful. Throws an XMP_Error exception if no derived name is found 62 // of if the temporary file cannot be created. 63 // 64 // Open - Open a file for read-only or read-write access. Returns the host-specific FileRef if 65 // successful, returns noFileRef if the path does not exist. Throws an XMP_Error exception for 66 // other errors. 67 // 68 // Close - Close a file. Does nothing if the FileRef is noFileRef. Throws an XMP_Error 69 // exception for any errors. 70 // 71 // SwapData - Swap the contents of two files. Both should be closed. Used as part of safe-save 72 // operations. On Mac, also swaps all non-data forks. Ideally just the contents should be 73 // swapped, but a 3-way rename will be used instead of reading and writing the contents. Uses a 74 // host file-swap service if available, even if that swaps more than the contents. Throws an 75 // XMP_Error exception for any errors. 76 // 77 // Rename - Rename a file or folder. The new path must not exist. Throws an XMP_Error exception 78 // for any errors. 79 // 80 // Delete - Deletes a file or folder. Does nothing if the path does not exist. Throws an 81 // XMP_Error exception for any errors. 82 // 83 // Seek - Change the I/O position of an open file, returning the new absolute offset. Uses the 84 // native host behavior for seeking beyond EOF. Throws an XMP_Error exception for any errors. 85 // 86 // Read - Read into a buffer returning the number of bytes read. Requests are limited to less 87 // than 2GB in case the host uses an SInt32 count. Throws an XMP_Error exception for errors. 88 // Reaching EOF or being at EOF is not an error. 89 // 90 // Write - Write from a buffer. Requests are limited to less than 2GB in case the host uses an 91 // SInt32 count. Throws an XMP_Error exception for any errors. 92 // 93 // Length - Returns the length of an open file in bytes. The I/O position is not changed. 94 // Throws an XMP_Error exception for any errors. 95 // 96 // SetEOF - Sets a new EOF offset. The I/O position may be changed. Throws an XMP_Error 97 // exception for any errors. 98 99 #if XMP_WinBuild 100 typedef HANDLE FileRef; 101 static const FileRef noFileRef = INVALID_HANDLE_VALUE; 102 #elif XMP_MacBuild 103 typedef FSIORefNum FileRef; 104 static const FileRef noFileRef = -1; 105 #elif XMP_UNIXBuild | XMP_iOSBuild 106 typedef int FileRef; 107 static const FileRef noFileRef = -1; 108 #endif 109 110 bool Exists ( const char* filePath ); 111 bool Writable ( const char* path, bool checkCreationPossible = false); 112 bool Create ( const char* filePath ); // Returns true if file exists or was created. 113 114 std::string GetCasePreservedName(const std::string& inputPath); 115 116 bool GetModifyDate ( const char* filePath, XMP_DateTime* modifyDate ); 117 118 std::string CreateTemp ( const char* sourcePath ); 119 120 enum { openReadOnly = true, openReadWrite = false }; 121 122 FileRef Open ( const char* filePath, bool readOnly ); 123 void Close ( FileRef file ); 124 125 void SwapData ( const char* sourcePath, const char* destPath ); 126 void Rename ( const char* oldPath, const char* newPath ); 127 void Delete ( const char* filePath ); 128 129 XMP_Int64 Seek ( FileRef file, XMP_Int64 offset, SeekMode mode ); 130 XMP_Uns32 Read ( FileRef file, void* buffer, XMP_Uns32 count ); 131 void Write ( FileRef file, const void* buffer, XMP_Uns32 count ); 132 XMP_Int64 Length ( FileRef file ); 133 void SetEOF ( FileRef file, XMP_Int64 length ); 134 Offset(FileRef file)135 inline XMP_Int64 Offset ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromCurrent ); }; Rewind(FileRef file)136 inline XMP_Int64 Rewind ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromStart ); }; // Always returns 0. ToEOF(FileRef file)137 inline XMP_Int64 ToEOF ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromEnd ); }; 138 139 // ============================================================================================= 140 // Folder operations 141 // ================= 142 // 143 // ! The folder operations may be used anywhere. 144 // 145 // GetFileMode - Returns an enum telling if a path names a file, folder, other, or nothing. 146 // Never throws an exception. 147 // 148 // GetChildMode - Same as GetFileMode, but has separate parent path and child name parameters. 149 // 150 // OpenFolder - Initializes the iteration of a folder. 151 // 152 // CloseFolder - Terminates the iteration of a folder. 153 // 154 // GetNextChild - Steps an iteration of a folder. Returns false at the end. Otherwise returns 155 // true and the local name of the next child. All names starting with '.' are skipped. 156 // 157 // AutoFolder - A utility class to make sure a folder iteration is terminated at scope exit. 158 159 enum { kFMode_DoesNotExist, kFMode_IsFile, kFMode_IsFolder, kFMode_IsOther }; 160 typedef XMP_Uns8 FileMode; 161 162 FileMode GetFileMode ( const char * path ); 163 FileMode GetChildMode ( const char * parentPath, const char * childName ); 164 165 #if XMP_WinBuild 166 typedef HANDLE FolderRef; 167 static const FolderRef noFolderRef = INVALID_HANDLE_VALUE; 168 #elif XMP_MacBuild 169 typedef DIR* FolderRef; 170 static const FolderRef noFolderRef = 0; 171 #elif XMP_UNIXBuild | XMP_iOSBuild 172 typedef DIR* FolderRef; 173 static const FolderRef noFolderRef = 0; 174 #endif 175 176 FolderRef OpenFolder ( const char* folderPath ); 177 void CloseFolder ( FolderRef folder ); 178 bool GetNextChild ( FolderRef folder, std::string* childName ); 179 180 class AutoFolder { // Used to make sure folder is closed at scope exit. 181 public: 182 FolderRef folder; AutoFolder()183 AutoFolder() : folder(noFolderRef) {}; ~AutoFolder()184 ~AutoFolder() { this->Close(); }; Close()185 void Close() { CloseFolder ( this->folder ); this->folder = noFolderRef; }; 186 }; 187 188 }; 189 190 #endif // __Host_IO_hpp__ 191