#ifndef __Host_IO_hpp__ #define __Host_IO_hpp__ 1 // ================================================================================================= // Copyright 2010 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 "public/include/XMP_Const.h" #include "public/include/XMP_IO.hpp" #include #if XMP_WinBuild #include #elif XMP_MacBuild #include #include // Mac uses the POSIX folder functions. #elif XMP_UNIXBuild | XMP_iOSBuild #include #else #error "Unknown host platform." #endif // ================================================================================================= // Host_IO is a collection of minimal convenient wrappers for host I/O services. It is intentionally // a namespace and not a class. No state is kept here, these are just wrappers that provide a common // internal API for basic I/O services that differ from host to host. namespace Host_IO { // ============================================================================================= // File operations // =============== // // ! The file operations should only be used in the implementation of XMPFiles_IO. // // Exists - Returns true if the path exists, whether as a file, folder, or anything else. Never // throws an exception. // // Writable - Returns true // a. In case checkCreationPossible is false check for existence and writable permissions. // b. In case checkCreationPossible is true and path is not existence, check permissions of parent folder. // // Create - Create a file if possible, return true if successful. Return false if the file // already exists. Throw an XMP_Error exception if the file cannot be created or if the path // already exists but is not a file. // // GetModifyDate - Return the file system modification date. Returns false if the file or folder // does not exist. // // CreateTemp - Create a (presumably) temporary file related to some other file. The source // file path is passed in, a derived name is selected in the same folder. The source file need // not exist, but all folders in the path must exist. The derived name is guaranteed to not // already exist. A limited number of attempts are made to select a derived name. Returns the // temporary file path if successful. Throws an XMP_Error exception if no derived name is found // of if the temporary file cannot be created. // // Open - Open a file for read-only or read-write access. Returns the host-specific FileRef if // successful, returns noFileRef if the path does not exist. Throws an XMP_Error exception for // other errors. // // Close - Close a file. Does nothing if the FileRef is noFileRef. Throws an XMP_Error // exception for any errors. // // SwapData - Swap the contents of two files. Both should be closed. Used as part of safe-save // operations. On Mac, also swaps all non-data forks. Ideally just the contents should be // swapped, but a 3-way rename will be used instead of reading and writing the contents. Uses a // host file-swap service if available, even if that swaps more than the contents. Throws an // XMP_Error exception for any errors. // // Rename - Rename a file or folder. The new path must not exist. Throws an XMP_Error exception // for any errors. // // Delete - Deletes a file or folder. Does nothing if the path does not exist. Throws an // XMP_Error exception for any errors. // // Seek - Change the I/O position of an open file, returning the new absolute offset. Uses the // native host behavior for seeking beyond EOF. Throws an XMP_Error exception for any errors. // // Read - Read into a buffer returning the number of bytes read. Requests are limited to less // than 2GB in case the host uses an SInt32 count. Throws an XMP_Error exception for errors. // Reaching EOF or being at EOF is not an error. // // Write - Write from a buffer. Requests are limited to less than 2GB in case the host uses an // SInt32 count. Throws an XMP_Error exception for any errors. // // Length - Returns the length of an open file in bytes. The I/O position is not changed. // Throws an XMP_Error exception for any errors. // // SetEOF - Sets a new EOF offset. The I/O position may be changed. Throws an XMP_Error // exception for any errors. #if XMP_WinBuild typedef HANDLE FileRef; static const FileRef noFileRef = INVALID_HANDLE_VALUE; #elif XMP_MacBuild typedef FSIORefNum FileRef; static const FileRef noFileRef = -1; #elif XMP_UNIXBuild | XMP_iOSBuild typedef int FileRef; static const FileRef noFileRef = -1; #endif bool Exists ( const char* filePath ); bool Writable ( const char* path, bool checkCreationPossible = false); bool Create ( const char* filePath ); // Returns true if file exists or was created. std::string GetCasePreservedName(const std::string& inputPath); bool GetModifyDate ( const char* filePath, XMP_DateTime* modifyDate ); std::string CreateTemp ( const char* sourcePath ); enum { openReadOnly = true, openReadWrite = false }; FileRef Open ( const char* filePath, bool readOnly ); void Close ( FileRef file ); void SwapData ( const char* sourcePath, const char* destPath ); void Rename ( const char* oldPath, const char* newPath ); void Delete ( const char* filePath ); XMP_Int64 Seek ( FileRef file, XMP_Int64 offset, SeekMode mode ); XMP_Uns32 Read ( FileRef file, void* buffer, XMP_Uns32 count ); void Write ( FileRef file, const void* buffer, XMP_Uns32 count ); XMP_Int64 Length ( FileRef file ); void SetEOF ( FileRef file, XMP_Int64 length ); inline XMP_Int64 Offset ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromCurrent ); }; inline XMP_Int64 Rewind ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromStart ); }; // Always returns 0. inline XMP_Int64 ToEOF ( FileRef file ) { return Host_IO::Seek ( file, 0, kXMP_SeekFromEnd ); }; // ============================================================================================= // Folder operations // ================= // // ! The folder operations may be used anywhere. // // GetFileMode - Returns an enum telling if a path names a file, folder, other, or nothing. // Never throws an exception. // // GetChildMode - Same as GetFileMode, but has separate parent path and child name parameters. // // OpenFolder - Initializes the iteration of a folder. // // CloseFolder - Terminates the iteration of a folder. // // GetNextChild - Steps an iteration of a folder. Returns false at the end. Otherwise returns // true and the local name of the next child. All names starting with '.' are skipped. // // AutoFolder - A utility class to make sure a folder iteration is terminated at scope exit. enum { kFMode_DoesNotExist, kFMode_IsFile, kFMode_IsFolder, kFMode_IsOther }; typedef XMP_Uns8 FileMode; FileMode GetFileMode ( const char * path ); FileMode GetChildMode ( const char * parentPath, const char * childName ); #if XMP_WinBuild typedef HANDLE FolderRef; static const FolderRef noFolderRef = INVALID_HANDLE_VALUE; #elif XMP_MacBuild typedef DIR* FolderRef; static const FolderRef noFolderRef = 0; #elif XMP_UNIXBuild | XMP_iOSBuild typedef DIR* FolderRef; static const FolderRef noFolderRef = 0; #endif FolderRef OpenFolder ( const char* folderPath ); void CloseFolder ( FolderRef folder ); bool GetNextChild ( FolderRef folder, std::string* childName ); class AutoFolder { // Used to make sure folder is closed at scope exit. public: FolderRef folder; AutoFolder() : folder(noFolderRef) {}; ~AutoFolder() { this->Close(); }; void Close() { CloseFolder ( this->folder ); this->folder = noFolderRef; }; }; }; #endif // __Host_IO_hpp__