core/vil/vil_stream_fstream.cxx
Go to the documentation of this file.
00001 // This is core/vil/vil_stream_fstream.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vil_stream_fstream.h"
00007 #include <vcl_cassert.h>
00008 #include <vcl_limits.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_ios.h>
00011 
00012 static vcl_ios_openmode modeflags(char const* mode)
00013 {
00014   if (*mode == 0)
00015     return vcl_ios_openmode(0);
00016 
00017   if (*mode == 'r') {
00018     if (mode[1] == '+' || mode[1] == 'w')
00019       return vcl_ios_in | vcl_ios_out | modeflags(mode+2);
00020     else
00021       return vcl_ios_in | modeflags(mode+1);
00022   }
00023 
00024   if (*mode == 'w') {
00025     if (mode[1] == '+')
00026       return vcl_ios_in | vcl_ios_out | vcl_ios_trunc | modeflags(mode+2);
00027     else
00028       return vcl_ios_out | vcl_ios_trunc | modeflags(mode+1);
00029   }
00030 
00031   vcl_cerr << vcl_endl << __FILE__ ": DODGY MODE " << mode << vcl_endl;
00032   return vcl_ios_openmode(0);
00033 }
00034 
00035 #define xerr if (true) ; else (vcl_cerr << "vcl_fstream#" << id_ << ": ")
00036 
00037 static int id = 0;
00038 
00039 vil_stream_fstream::vil_stream_fstream(char const* fn, char const* mode):
00040   flags_(modeflags(mode)),
00041   f_(fn, flags_ | vcl_ios_binary), // need ios::binary on windows.
00042   end_( -1 )
00043 {
00044   id_ = ++id;
00045   xerr << "vil_stream_fstream(\"" << fn << "\", \""<<mode<<"\") = " << id_ << '\n';
00046 #if 0
00047   if (!f_) {
00048     vcl_cerr << "vil_stream_fstream::Could not open [" << fn << "]\n";
00049   }
00050 #endif // 0
00051 }
00052 
00053 #if defined(VCL_WIN32) && VXL_USE_WIN_WCHAR_T
00054 vil_stream_fstream::vil_stream_fstream(wchar_t const* fn, char const* mode):
00055   flags_(modeflags(mode)),
00056   f_(fn, flags_ | vcl_ios_binary), // need ios::binary on windows.
00057   end_( -1 )
00058 {
00059   id_ = ++id;
00060 }
00061 #endif //defined(VCL_WIN32) && VXL_USE_WIN_WCHAR_T
00062 
00063 #if 0
00064 vil_stream_fstream::vil_stream_fstream(vcl_fstream& f):
00065   f_(f.rdbuf()->fd()),
00066   end_( -1 )
00067 {
00068 }
00069 #endif // 0
00070 
00071 vil_stream_fstream::~vil_stream_fstream()
00072 {
00073   xerr << "vil_stream_fstream# " << id_ << " being deleted\n";
00074 }
00075 
00076 vil_streampos vil_stream_fstream::write(void const* buf, vil_streampos n)
00077 {
00078   assert(id > 0);
00079   //assures that cast (below) will be ok
00080   //but the FreeBSD-4.9-gcc-2.95.4 build seems to have a problem
00081   //with it, so I'm commenting it out
00082 #ifndef VCL_GCC_295
00083   assert( n <= vcl_numeric_limits<vcl_streamoff>::max() );
00084 #endif
00085 
00086   if (!(flags_ & vcl_ios_out)) {
00087     vcl_cerr << "vil_stream_fstream: write failed, not a vcl_ostream\n";
00088     return 0;
00089   }
00090 
00091   vil_streampos a = tell();
00092   xerr << "write " << n << vcl_endl;
00093   f_.write((char const*)buf, (vcl_streamoff)n);
00094   if (!f_.good())
00095     vcl_cerr << ("vil_stream_fstream: ERROR: write failed!\n");
00096   vil_streampos b = tell();
00097   f_.flush();
00098   return b-a;
00099 }
00100 
00101 
00102 vil_streampos vil_stream_fstream::read(void* buf, vil_streampos n)
00103 {
00104   assert(id > 0);
00105   //assures that cast (below) will be ok
00106   //but the FreeBSD-4.9-gcc-2.95.4 build seems to have a problem
00107   //with it, so I'm commenting it out
00108 #ifndef VCL_GCC_295
00109   assert( n <= vcl_numeric_limits<vcl_streamoff>::max() );
00110 #endif
00111 
00112   if (!(flags_ & vcl_ios_in))
00113     return 0;
00114 
00115   vil_streampos a = tell();
00116   xerr << "read " << n << vcl_endl;
00117   f_.read((char *)buf, (vcl_streamoff)n);
00118 
00119   // fsm  This is for gcc 2.95 :
00120   // If we try to read more data than is in the file, the good()
00121   // function will return false even though bad() returns false
00122   // too. The stream is actually fine but we need to clear the
00123   // eof flag to use it again.
00124   // iscott@man It does something similar under Windows, but has the added
00125   // advantage, of making tell() return a sensible value (instead
00126   // of -1)
00127   if (!f_.good() && !f_.bad() && f_.eof())
00128     f_.clear(); // allows subsequent operations
00129 
00130   vil_streampos b = tell();
00131 
00132   vil_streampos numread = b-a;
00133   if (b < a) { xerr << "urgh!\n"; return numread; }
00134   if (numread != n) { xerr << "only read " << numread << vcl_endl; }
00135   return numread;
00136 }
00137 
00138 vil_streampos vil_stream_fstream::tell() const
00139 {
00140   assert(id > 0);
00141   if (flags_ & vcl_ios_in) {
00142     xerr << "tellg\n";
00143     return f_.tellg();
00144   }
00145 
00146   if (flags_ & vcl_ios_out) {
00147     xerr << "tellp\n";
00148     return f_.tellp();
00149   }
00150 
00151   assert(false); // did you get here? use at least one of vcl_ios_in, vcl_ios_out.
00152   return (vil_streampos)(-1L);
00153 }
00154 
00155 void vil_stream_fstream::seek(vil_streampos position)
00156 {
00157   assert(id > 0);
00158   //assures that cast (below) will be ok
00159   //but the FreeBSD-4.9-gcc-2.95.4 build seems to have a problem
00160   //with it, so I'm commenting it out
00161 #ifndef VCL_GCC_295
00162   assert( position <= vcl_numeric_limits< vcl_streamoff >::max() );
00163 #endif
00164 
00165   bool fi = (flags_ & vcl_ios_in)  != 0;
00166   bool fo = (flags_ & vcl_ios_out) != 0;
00167 
00168   if (fi && fo) {
00169     xerr << "seekg and seekp to " << position << vcl_endl;
00170     if (position != vil_streampos(f_.tellg())) {
00171       f_.seekg((vcl_streamoff)position);
00172       f_.seekp((vcl_streamoff)position);
00173       assert(f_.good());
00174     }
00175   }
00176 
00177   else if (fi) {
00178     xerr << "seek to " << position << vcl_endl;
00179     if (position != vil_streampos(f_.tellg())) {
00180       f_.seekg((vcl_streamoff)position);
00181       assert(f_.good());
00182     }
00183   }
00184 
00185   else if (fo) {
00186     xerr << "seekp to " << position << vcl_endl;
00187     vcl_streamoff at = f_.tellp();
00188     if (position != at) {
00189       xerr << "seekp to " << position << ", at " << (long)f_.tellp() << vcl_endl;
00190       f_.seekp((vcl_streamoff)position);
00191       assert(f_.good());
00192     }
00193   }
00194   else
00195     assert(false); // did you get here? use at least one of vcl_ios_in, vcl_ios_out.
00196 }
00197 
00198 vil_streampos vil_stream_fstream::file_size() const
00199 {
00200   // if not already computed, do so
00201   if ( end_ == -1 ) {
00202     vcl_streampos curr = f_.tellg();
00203     f_.seekg( 0, vcl_ios_end );
00204     end_ = f_.tellg();
00205     f_.seekg( curr );
00206   }
00207 
00208   return end_;
00209 }