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