Joshua
open source statistical hierarchical phrase-based machine translation system
|
00001 #ifndef UTIL_FILE_H 00002 #define UTIL_FILE_H 00003 00004 #include "util/exception.hh" 00005 #include "util/scoped.hh" 00006 #include "util/string_piece.hh" 00007 00008 #include <cstddef> 00009 #include <cstdio> 00010 #include <string> 00011 #include <stdint.h> 00012 00013 namespace util { 00014 00015 class scoped_fd { 00016 public: 00017 scoped_fd() : fd_(-1) {} 00018 00019 explicit scoped_fd(int fd) : fd_(fd) {} 00020 00021 ~scoped_fd(); 00022 00023 void reset(int to = -1) { 00024 scoped_fd other(fd_); 00025 fd_ = to; 00026 } 00027 00028 int get() const { return fd_; } 00029 00030 int operator*() const { return fd_; } 00031 00032 int release() { 00033 int ret = fd_; 00034 fd_ = -1; 00035 return ret; 00036 } 00037 00038 private: 00039 int fd_; 00040 00041 scoped_fd(const scoped_fd &); 00042 scoped_fd &operator=(const scoped_fd &); 00043 }; 00044 00045 struct scoped_FILE_closer { 00046 static void Close(std::FILE *file); 00047 }; 00048 typedef scoped<std::FILE, scoped_FILE_closer> scoped_FILE; 00049 00050 /* Thrown for any operation where the fd is known. */ 00051 class FDException : public ErrnoException { 00052 public: 00053 explicit FDException(int fd) throw(); 00054 00055 virtual ~FDException() throw(); 00056 00057 // This may no longer be valid if the exception was thrown past open. 00058 int FD() const { return fd_; } 00059 00060 // Guess from NameFromFD. 00061 const std::string &NameGuess() const { return name_guess_; } 00062 00063 private: 00064 int fd_; 00065 00066 std::string name_guess_; 00067 }; 00068 00069 // End of file reached. 00070 class EndOfFileException : public Exception { 00071 public: 00072 EndOfFileException() throw(); 00073 ~EndOfFileException() throw(); 00074 }; 00075 00076 // Open for read only. 00077 int OpenReadOrThrow(const char *name); 00078 // Create file if it doesn't exist, truncate if it does. Opened for write. 00079 int CreateOrThrow(const char *name); 00080 00090 bool InputPathIsStdin(StringPiece path); 00091 00101 bool OutputPathIsStdout(StringPiece path); 00102 00103 // Return value for SizeFile when it can't size properly. 00104 const uint64_t kBadSize = (uint64_t)-1; 00105 uint64_t SizeFile(int fd); 00106 uint64_t SizeOrThrow(int fd); 00107 00108 void ResizeOrThrow(int fd, uint64_t to); 00109 00110 std::size_t PartialRead(int fd, void *to, std::size_t size); 00111 void ReadOrThrow(int fd, void *to, std::size_t size); 00112 std::size_t ReadOrEOF(int fd, void *to_void, std::size_t size); 00113 00114 void WriteOrThrow(int fd, const void *data_void, std::size_t size); 00115 void WriteOrThrow(FILE *to, const void *data, std::size_t size); 00116 00117 /* These call pread/pwrite in a loop. However, on Windows they call ReadFile/ 00118 * WriteFile which changes the file pointer. So it's safe to call ErsatzPRead 00119 * and ErsatzPWrite concurrently (or any combination thereof). But it changes 00120 * the file pointer on windows, so it's not safe to call concurrently with 00121 * anything that uses the implicit file pointer e.g. the Read/Write functions 00122 * above. 00123 */ 00124 void ErsatzPRead(int fd, void *to, std::size_t size, uint64_t off); 00125 void ErsatzPWrite(int fd, const void *data_void, std::size_t size, uint64_t off); 00126 00127 void FSyncOrThrow(int fd); 00128 00129 // Seeking 00130 void SeekOrThrow(int fd, uint64_t off); 00131 void AdvanceOrThrow(int fd, int64_t off); 00132 void SeekEnd(int fd); 00133 00134 std::FILE *FDOpenOrThrow(scoped_fd &file); 00135 std::FILE *FDOpenReadOrThrow(scoped_fd &file); 00136 00137 // Temporary files 00138 // Append a / if base is a directory. 00139 void NormalizeTempPrefix(std::string &base); 00140 int MakeTemp(const StringPiece &prefix); 00141 std::FILE *FMakeTemp(const StringPiece &prefix); 00142 00143 // dup an fd. 00144 int DupOrThrow(int fd); 00145 00146 /* Attempt get file name from fd. This won't always work (i.e. on Windows or 00147 * a pipe). The file might have been renamed. It's intended for diagnostics 00148 * and logging only. 00149 */ 00150 std::string NameFromFD(int fd); 00151 00152 } // namespace util 00153 00154 #endif // UTIL_FILE_H