File.h

00001 // $Id: File.h 21 2010-09-05 04:18:17Z cschwarz1 $
00002 
00003 #ifndef BASE_FILE_H
00004 #define BASE_FILE_H
00005 
00006 #ifndef _WIN32
00007     #include <cerrno>
00008 #endif
00009 #include "Global.h"
00010 #include "IOException.h"
00011 #include "Stat.h"
00012 #include "Unicode.h"
00013 
00014 namespace base {
00016 
00020     class PPBASE_EXPORT FileBase {
00021     public:
00022     #ifdef _WIN32
00023         typedef HANDLE handle_type;
00024     #else
00025         typedef int handle_type;   
00026     #endif
00027         typedef size_t size_type;  
00028 
00030         enum {
00031             ofReadOnly  = 0x01,                
00032             ofWriteOnly = 0x02,                
00033             ofReadWrite = 0x03,                
00034             ofAppend    = 0x04,                
00035             ofCreate    = 0x08,                
00036             ofTruncate  = 0x10,                
00037             ofExclusive = 0x20,                
00038             ofWriteCreate = 0x0a,              
00039             ofWriteCreateTruncate = 0x1a,      
00040             ofReadWriteCreate = 0x0b,          
00041             ofReadWriteCreateTruncate = 0x1b   
00042         };
00043 
00045         enum {
00046             tempDelNever = 0,                  
00047             tempDelOnClose = 1,                
00048             tempDelOnDelete = 2                
00049         };
00050 
00051     protected:
00053         FileBase();
00054 
00056 
00063         FileBase(const char *name, int flags = ofReadOnly, int mode = 0666);
00064 
00066 
00073         FileBase(const String &name, int flags = ofReadOnly, int mode = 0666);
00074 
00076 
00085         FileBase(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3);
00086 
00088         ~FileBase();
00089 
00090     public:
00092 
00097         static void chmod(const String &path, unsigned mode);
00098 
00100 
00106         static void chown(const String &path, unsigned uid, unsigned gid);
00107 
00109 
00112         void close();
00113 
00115 
00119         static void copy(const String &src, const String &dst);
00120 
00122 
00126         static bool exists(const String &path);
00127 
00129 
00132         void flush();
00133 
00135 
00138     #ifdef _WIN32
00139         HANDLE getFD() const;
00140     #else
00141         int getFD() const;
00142     #endif
00143 
00145         size_type getLineNo() const;
00146 
00148         String getName() const;
00149 
00151 
00155         static String getTempPath();
00156 
00158 
00162         static bool isAbsoluteFileName(const String &name);
00163 
00165 
00168         bool isOpen() const;
00169 
00171 
00178         bool lock(bool exclusive = true, bool block = true);
00179 
00181 
00187         static String makeFileName(const String &dname, const String &fname, bool fixdelim = true);
00188 
00190 
00195         static void mkfifo(const String &name, unsigned mode);
00196 
00198 
00203         static void move(const String &oldpath, const String &newpath);
00204 
00206 
00215         void open(const char *name, int flags = ofReadOnly, int mode = 0666, bool temp = false, bool stayopen = false);
00216 
00218 
00227         void open(const String &name, int flags = ofReadOnly, int mode = 0666, bool temp = false, bool stayopen = false);
00228 
00230 
00239         void open(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3);
00240 
00242 
00249         void openTemp(const String &name, const String &dir = "", int tempdel = tempDelOnClose);
00250 
00252 
00259         size_type read(void *buf, size_type count, bool exact = false);
00260 
00262 
00269         size_type read(String &rbuf, size_type count, bool exact = false);
00270 
00272 
00278         bool readln(String &ret, bool strip = false);
00279 
00281 
00286         bool readstr(String &ret);
00287 
00289 
00298         size_type readto(void *buf, size_type count, bool exact, unsigned timeout, bool *rtimedout);
00299 
00301 
00306         static void rename(const String &oldpath, const String &newpath);
00307 
00309 
00313         void setBlocking(bool blocking);
00314 
00316 
00325         void setReadBuffer(size_type size);
00326 
00328 
00337         void setWriteBuffer(size_type size);
00338 
00340         template<class charT, class traits> static void split(const StringT<charT, traits> &filename, StringT<charT, traits> &dirname, StringT<charT, traits> &basename);
00341 
00343 
00349         static void symlink(const String &oldpath, const String &newpath, bool force = false);
00350 
00352 
00361         static void touch(const String &path, bool parent = false, unsigned dmode = 0755, unsigned fmode = 0644,
00362             unsigned uid = (unsigned)-1, unsigned gid = (unsigned)-1);
00363 
00365 
00370         static void unlink(const String &path, bool force = false);
00371 
00373 
00376         void unlock();
00377 
00379 
00386         size_type write(const void *buf, size_type count, bool exact = true);
00387 
00389 
00395         size_type write(const String &buf, bool exact = true);
00396 
00398 
00404         size_type writef(const char *fmt, ...)
00405         #if __GNUC__
00406             __attribute__((format(printf, 2, 3)))
00407         #endif
00408         ;
00409     
00411 
00417         size_type writevf(const char *fmt, va_list ap);
00418 
00419     private:
00421 
00426         void read(unsigned timeout = 0, bool *rtimedout = NULL);
00427 
00429 
00432         void write();
00433 
00434     protected:
00435     #ifdef _WIN32
00436         HANDLE       _ev;          
00437     #endif
00438         handle_type  _fd;          
00439         size_type    _lineno;      
00440         String       _name;        
00441         char        *_rdbuf;       
00442         size_type    _rdbufpos;    
00443         size_type    _rdbufsize;   
00444         size_type    _rdbufused;   
00445         bool         _stayopen;    
00446         bool         _temp;        
00447         int          _tempdel;     
00448         char        *_wrbuf;       
00449         size_type    _wrbufsize;   
00450         size_type    _wrbufused;   
00451 
00453         DISALLOW_COPY_CONSTRUCTOR_AND_ASSIGNMENT(FileBase);
00454     };
00455 
00456     template<class charT, class traits> void FileBase::split(const StringT<charT, traits> &filename, StringT<charT, traits> &dirname, StringT<charT, traits> &basename) {
00457         typename StringT<charT, traits>::size_type pos;
00458 
00459         pos = filename.rfind(traits::path_separator_char);
00460         if (pos == StringT<charT, traits>::npos) {
00461             dirname.clear();
00462             basename = filename;
00463         } else {
00464             dirname.assign(filename, 0, pos);
00465             basename.assign(filename, pos + 1);
00466         }
00467     }
00468 
00470 
00474     template<class sizeT, class traits = SizeTraits<sizeT> > class FileT: public FileBase {
00475     public:
00476         typedef sizeT size_type;   
00477 
00479         FileT(): FileBase() {}
00480 
00482 
00489         FileT(const char *name, int flags = ofReadOnly, int mode = 0666):
00490             FileBase(name, flags, mode) {}
00491 
00493 
00500         FileT(const String &name, int flags = ofReadOnly, int mode = 0666):
00501             FileBase(name, flags, mode) {}
00502 
00504 
00513         FileT(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3):
00514             FileBase(fd, name, temp, stayopen, allocbufs) {}
00515 
00517 
00521         StatT<sizeT> fstat() const {
00522         #ifdef _WIN32
00523             BY_HANDLE_FILE_INFORMATION ret;
00524 
00525             if (!GetFileInformationByHandle(_fd, &ret))
00526                 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00527         #else
00528             typename traits::stat_type ret;
00529 
00530             if (traits::fstat(_fd, &ret))
00531                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00532         #endif
00533             return ret;
00534         }
00535 
00537 
00541         sizeT getPos() const {
00542         #ifdef _WIN32
00543             traits::ssize_type ret;
00544 
00545             ret = traits::lseek(_fd, 0, FILE_CURRENT);
00546             if (ret == INVALID_SET_FILE_POINTER)
00547                 if (GetLastError() != NO_ERROR)
00548                     throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to get position in %s"), _name.c_str());
00549         #else
00550             typename traits::ssize_type ret;
00551 
00552             if ((ret = traits::lseek(_fd, 0, SEEK_CUR)) < 0)
00553                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to get position in %s"), _name.c_str());
00554         #endif
00555             if (static_cast<typename traits::ssize_type>(_rdbufused - _rdbufpos) < ret)
00556                 ret -= static_cast<typename traits::ssize_type>(_rdbufused - _rdbufpos);
00557             else
00558                 ret = 0;
00559             return ret;
00560         }
00561 
00563 
00567         void seek(sizeT pos) {
00568             flush();
00569         #ifdef _WIN32
00570             if (traits::lseek(_fd, static_cast<traits::ssize_type>(pos), FILE_BEGIN) == INVALID_SET_FILE_POINTER)
00571                 if (GetLastError() != NO_ERROR)
00572                     throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to seek to %llu in %s"), pos, _name.c_str());
00573         #else
00574             if (traits::lseek(_fd, pos, SEEK_SET) < 0)
00575                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to seek to %llu in %s"), static_cast<u_longlong_t>(pos), _name.c_str());
00576         #endif
00577             _rdbufpos = _rdbufused = 0;
00578         }
00579 
00581         void seekEOF() {
00582             flush();
00583         #ifdef _WIN32
00584             if (traits::lseek(_fd, 0, FILE_END) == INVALID_SET_FILE_POINTER)
00585                 if (GetLastError() != NO_ERROR)
00586                     throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to seek to EOF in %s"), _name.c_str());
00587         #else
00588             if (traits::lseek(_fd, 0, SEEK_END) < 0)
00589                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to seek to EOF in %s"), _name.c_str());
00590         #endif
00591             _rdbufpos = _rdbufused = 0;
00592         }
00593 
00595 
00599         sizeT size() const {
00600         #ifdef _WIN32
00601             BY_HANDLE_FILE_INFORMATION st;
00602 
00603             if (!GetFileInformationByHandle(_fd, &st))
00604                 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to fstat %s"), _name.c_str());
00605             return (static_cast<u_longlong_t>(st.nFileSizeHigh) << 32) | st.nFileSizeLow;
00606         #else
00607             typename traits::stat_type st;
00608 
00609             if (traits::fstat(_fd, &st))
00610                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00611             return st.st_size;
00612         #endif
00613         }
00614 
00616 
00620         static StatT<sizeT> stat(const String &path) {
00621         #ifdef _WIN32
00622             if (Unicode::isUtf8(path)) {
00623                 HANDLE           dir;
00624                 WIN32_FIND_DATAW ret;
00625 
00626                 dir = FindFirstFileW(Unicode::utf8ToUtf16(path).c_str(), &ret);
00627                 if (dir == INVALID_HANDLE_VALUE)
00628                     throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to stat %s"), path.c_str());
00629                 FindClose(dir);
00630                 return ret;
00631             } else {
00632                 HANDLE           dir;
00633                 WIN32_FIND_DATAA ret;
00634 
00635                 dir = FindFirstFileA(path.c_str(), &ret);
00636                 if (dir == INVALID_HANDLE_VALUE)
00637                     throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to stat %s"), path.c_str());
00638                 FindClose(dir);
00639                 return ret;
00640             }
00641         #else
00642             typename traits::stat_type ret;
00643 
00644             if (traits::stat(path.c_str(), &ret))
00645                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to stat %s"), path.c_str());
00646             return ret;
00647         #endif
00648         }
00649 
00651 
00655         void truncate(sizeT len) {
00656         #ifdef _WIN32
00657             if (_fd == INVALID_HANDLE_VALUE)
00658                 throw IOException(IOException::errFile, 0, Global::gettext("File not open"));
00659             seek(len);
00660             if (!SetEndOfFile(_fd))
00661                 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to truncate %s to %llu"), _name.c_str(), len);
00662         #else
00663             if (_fd < 0)
00664                 throw IOException(IOException::errFile, EBADF, "%s", Global::gettext("File not open"));
00665             if (traits::truncate(_fd, len))
00666                 throw IOException(IOException::errFile, errno, Global::gettext("Unable to truncate %s to %llu"), _name.c_str(), static_cast<u_longlong_t>(len));
00667         #endif
00668         }
00669 
00671         DISALLOW_COPY_CONSTRUCTOR_AND_ASSIGNMENT(FileT);
00672     };
00673 
00674     typedef FileT<size_t>       File;   
00675     typedef FileT<u_longlong_t> LFile;  
00676 }
00677 
00678 #endif