core/vil/vil_stream_section.cxx
Go to the documentation of this file.
00001 // This is core/vil/vil_stream_section.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "vil_stream_section.h"
00010 #include <vcl_cassert.h>
00011 #include <vcl_iostream.h>
00012 
00013 // underlying_: pointer to underlying stream.
00014 // begin_     : start of section in the underlying stream.
00015 // end_       : end of section in the underlying stream. -1 if there is no (explicit) end.
00016 // current_   : current position (in the underlying stream) of the adapted stream.
00017 
00018 vil_stream_section::vil_stream_section(vil_stream *underlying, int begin)
00019   : underlying_(underlying)
00020   , begin_(begin)
00021   , end_((vil_streampos)(-1L))
00022   , current_(begin)
00023 {
00024   assert(underlying != 0);
00025   assert(begin >= 0);
00026   underlying_->ref();
00027 }
00028 
00029 vil_stream_section::vil_stream_section(vil_stream *underlying, int begin, int end)
00030   : underlying_(underlying)
00031   , begin_(begin)
00032   , end_(end)
00033   , current_(begin)
00034 {
00035   assert(underlying != 0);
00036   assert(begin >= 0);
00037   assert(begin <= end);
00038   underlying->ref();
00039 }
00040 
00041 vil_stream_section::~vil_stream_section()
00042 {
00043   // unreffing the underlying stream might cause deletion of *this, so
00044   // zero out the pointer first.
00045   vil_stream *u = underlying_;
00046   underlying_ = 0;
00047   u->unref();
00048 }
00049 
00050 vil_streampos vil_stream_section::write(void const* buf, vil_streampos n)
00051 {
00052   assert(n >= 0); // wouldn't you want to be told?
00053 
00054   // huh? this should never happen, even if someone else is
00055   // manipulating the underlying stream too.
00056   assert(begin_<=current_);
00057   if (end_ != -1L)
00058     assert(current_<=end_);
00059 
00060   // shrink given buffer so it fits into our section.
00061   if (end_ != -1L  &&  current_ + n > end_)
00062     n = end_ - current_;
00063 
00064   // seek to where we have been telling the clients we are.
00065   underlying_->seek(current_);
00066 
00067   // this could be a bug in the caller's code or merely a
00068   // failure to seek on underlying stream.
00069   assert(underlying_->tell() == current_);
00070 
00071   vil_streampos nb = underlying_->write(buf, n);
00072   if (nb != -1L)
00073     current_ += nb;
00074   return nb;
00075 }
00076 
00077 vil_streampos vil_stream_section::read(void* buf, vil_streampos n)
00078 {
00079   assert(n >= 0); // wouldn't you want to be told?
00080 
00081   // huh? this should never happen, even if someone else is
00082   // manipulating the underlying stream too.
00083   assert(begin_<=current_);
00084   if (end_ != -1L)
00085     assert(current_<=end_);
00086 
00087   // shrink given buffer so it fits into our section.
00088   if (end_ != -1L  &&  current_ + n > end_)
00089     n = end_ - current_;
00090 
00091   // seek to where we have been telling the clients we are.
00092   underlying_->seek(current_);
00093 
00094   // this could be a bug in the caller's code or merely a
00095   // failure to seek on underlying stream.
00096   assert(underlying_->tell() == current_);
00097 
00098   vil_streampos nb = underlying_->read(buf, n);
00099   if (nb != -1L)
00100     current_ += nb;
00101   return nb;
00102 }
00103 
00104 void vil_stream_section::seek(vil_streampos position)
00105 {
00106   assert(position >= 0); // I would want to be told about this.
00107 
00108   if (end_ != -1L  &&  begin_ + position > end_) {
00109     vcl_cerr << __FILE__ << ": attempt to seek past given section (failed).\n";
00110     return;
00111   }
00112   else
00113     current_ = begin_ + position;
00114 }
00115 
00116 vil_streampos vil_stream_section::file_size() const
00117 {
00118   return end_ >= begin_ ? end_ - begin_ : underlying_->file_size() - begin_;
00119 }