core/vil/vil_stream_fstream64.cxx
Go to the documentation of this file.
00001 // This is core/vil/vil_stream_fstream64.cxx
00002 #ifdef VIL_USE_FSTREAM64 // only compile this file when needed
00003 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00004 #pragma implementation
00005 #endif
00006 
00007 #include "vil_stream_fstream64.h"
00008 #include <vcl_cassert.h>
00009 #include <vcl_iostream.h> //for vcl_cerr
00010 
00011 #if defined(WIN32)
00012 #include <io.h>
00013 #endif
00014 #include <fcntl.h>
00015 #include <sys/stat.h>
00016 
00017 #ifndef WIN32
00018 //RaR: My attempt at cross-platform compatibility
00019 //     This stuff really isn't that important because
00020 //     this file is only added to the configuration
00021 //     for WIN32 builds
00022 #define _O_RDWR O_RDWR
00023 #define _O_RDONLY O_RDONLY
00024 #define _O_WRONLY O_WRONLY
00025 #define _O_BINARY 0
00026 #define _O_CREAT O_CREAT
00027 #define _S_IREAD S_IREAD
00028 #define _S_IWRITE S_IWRITE
00029 #define _open ::open
00030 #define _close ::close
00031 #define _telli64(fd) ::lseek(fd, 0, SEEK_CUR)
00032 #define _lseeki64 ::lseek
00033 #include <unistd.h>
00034 #define _commit ::fsync
00035 #define _read ::read
00036 #define _write ::write
00037 #endif
00038 
00039 #define xerr if (true) ; else (vcl_cerr << "vcl_fstream#" << fd_ << ": ")
00040 
00041 static int modeflags(char const* mode)
00042 {
00043   bool read = false,
00044        write = false;
00045 
00046   for ( unsigned int i = 0; mode[i] != 0; ++i ) {
00047     if ( mode[i] == 'r' )
00048       read = true;
00049     else if ( mode[i] == 'w' )
00050       write = true;
00051   }
00052 
00053   if ( read && write ) return _O_RDWR;
00054   else if ( read ) return _O_RDONLY;
00055   else if ( write ) return _O_WRONLY;
00056 
00057   vcl_cerr << '\n' << __FILE__ ": DODGY MODE " << mode << '\n';
00058   return 0;
00059 }
00060 
00061 
00062 vil_stream_fstream64::vil_stream_fstream64(char const* fn, char const* mode) :
00063   mode_( modeflags(mode) )
00064 {
00065   if ( mode_ == O_RDONLY ) {
00066     fd_ = _open( fn, mode_ | _O_BINARY  );
00067   } else {
00068     fd_ = _open( fn, mode_ | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE );
00069   }
00070   if ( fd_ == -1 ){
00071     vcl_cerr << "vil_stream_fstream64::Could not open [" << fn << "]\n";
00072   }
00073 }
00074 
00075 #if defined(VCL_WIN32) && VXL_USE_WIN_WCHAR_T
00076 vil_stream_fstream64::vil_stream_fstream64(wchar_t const* fn, char const* mode):
00077   mode_(modeflags(mode))
00078 {
00079   if ( mode_ == O_RDONLY )
00080     fd_ = _wopen( fn, mode_ | _O_BINARY  );
00081   else
00082     fd_ = _wopen( fn, mode_ | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE );
00083   if ( fd_ == -1 )
00084   {
00085     vcl_cerr << "vil_stream_fstream64::Could not open [" << fn << "]\n";
00086   }
00087 }
00088 #endif //defined(VCL_WIN32) && VXL_USE_WIN_WCHAR_T
00089 
00090 vil_stream_fstream64::~vil_stream_fstream64()
00091 {
00092   //xerr << "vil_stream_fstream64 # " << fd_ << " being deleted\n";
00093 
00094   if ( ok() ){
00095     _close( fd_ );
00096   }
00097 }
00098 
00099 vil_streampos vil_stream_fstream64::write(void const* buf, vil_streampos n)
00100 {
00101   assert(ok());
00102 
00103   if ( !( ( mode_ == _O_WRONLY ) ||
00104           ( mode_ == _O_RDWR ) ) )
00105   {
00106     vcl_cerr << "vil_stream_fstream64: write failed, stream not open for write\n";
00107     return 0;
00108   }
00109 
00110   //cast should be ok unless trying to write >2GB (not likely)
00111   int ret_val = _write( fd_, buf, (unsigned int)n );
00112   if ( ret_val == -1 ){
00113     vcl_cerr << ("vil_stream_fstream64: ERROR: write failed!\n");
00114     return 0;
00115   } else {
00116     //apparently calling _commit is relatively slow
00117     //for file types like pnm whose put_view() functions
00118     //write() one byte at a time, it takes minutes to write a
00119     //single (relatively) small file.  That's why we comment
00120     //out this commit() (ie. flush) logic.  All tests pass,
00121     //so this should be ok.
00122     //if ( _commit( fd_ ) == -1 ){
00123     //  return 0;
00124     //} else {
00125       return ret_val;
00126     //}
00127   }
00128 }
00129 
00130 
00131 vil_streampos vil_stream_fstream64::read(void* buf, vil_streampos n)
00132 {
00133   assert(ok());
00134 
00135   if ( !( ( mode_ == _O_RDONLY ) ||
00136           ( mode_ == _O_RDWR ) ) )
00137   {
00138     xerr << "vil_stream_fstream64: read failed, stream not open for read\n";
00139     return 0;
00140   }
00141   //cast should be ok unless trying to read >2GB
00142   int ret_val = _read( fd_, buf, (unsigned int)n );
00143   if ( ret_val == -1 )
00144     xerr << "read failed!\n";
00145   else if ( ret_val < n )
00146     xerr << "only read " << ret_val << vcl_endl;
00147 
00148   return ret_val;
00149 }
00150 
00151 vil_streampos vil_stream_fstream64::tell() const
00152 {
00153   assert(ok());
00154   return _telli64( fd_ );
00155 }
00156 
00157 void vil_stream_fstream64::seek(vil_streampos position)
00158 {
00159   assert(ok());
00160   long long ret_val = _lseeki64( fd_, position, SEEK_SET );
00161   if ( ret_val == -1L ){
00162     xerr << "error during seek.";
00163   }
00164 }
00165 
00166 vil_streampos vil_stream_fstream64::file_size() const
00167 {
00168   vil_streampos curr = tell();
00169   _lseeki64( fd_, 0, SEEK_END );
00170   vil_streampos end = tell();
00171   _lseeki64( fd_, curr, SEEK_SET );
00172   return end;
00173 }
00174 
00175 #endif // VIL_USE_FSTREAM64