stdiobuf.cc

Go to the documentation of this file.
00001 /** @file rutz/stdiobuf.cc wrap posix file descriptors in c++ iostreams */
00002 
00003 ///////////////////////////////////////////////////////////////////////
00004 //
00005 // Copyright (c) 2002-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Tue Feb 25 13:52:11 2003
00010 // commit: $Id: stdiobuf.cc 8249 2007-04-12 06:03:40Z rjpeters $
00011 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/stdiobuf.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00032 ///////////////////////////////////////////////////////////////////////
00033 
00034 #ifndef GROOVX_RUTZ_STDIOBUF_CC_UTC20050626084020_DEFINED
00035 #define GROOVX_RUTZ_STDIOBUF_CC_UTC20050626084020_DEFINED
00036 
00037 #include "rutz/stdiobuf.h"
00038 
00039 #include "rutz/error.h"
00040 
00041 #include <ios>
00042 #include <unistd.h>
00043 
00044 #include "rutz/debug.h"
00045 GVX_DBG_REGISTER
00046 #include "rutz/trace.h"
00047 
00048 void rutz::stdiobuf::init(int fd, int om, bool throw_exception)
00049 {
00050 GVX_TRACE("rutz::stdiobuf::init");
00051   m_filedes = fd;
00052 
00053   if (m_filedes >= 0)
00054     {
00055       m_mode = om;
00056     }
00057 
00058   if (throw_exception && !is_open())
00059     {
00060       throw rutz::error("couldn't open file stdiobuf", SRC_POS);
00061     }
00062 
00063   setg (buffer+s_pback_size,
00064         buffer+s_pback_size,
00065         buffer+s_pback_size);
00066 
00067   setp (buffer,
00068         buffer+s_buf_size-1);
00069 }
00070 
00071 rutz::stdiobuf::stdiobuf(FILE* f, int om, bool throw_exception) :
00072   m_mode(0), m_filedes(-1)
00073 {
00074 GVX_TRACE("rutz::stdiobuf::stdiobuf(FILE*)");
00075   init(fileno(f), om, throw_exception);
00076 }
00077 
00078 rutz::stdiobuf::stdiobuf(int fd, int om, bool throw_exception) :
00079   m_mode(0), m_filedes(-1)
00080 {
00081 GVX_TRACE("rutz::stdiobuf::stdiobuf(int)");
00082 
00083   init(fd, om, throw_exception);
00084 }
00085 
00086 void rutz::stdiobuf::close()
00087 {
00088 GVX_TRACE("rutz::stdiobuf::close");
00089   if (is_open())
00090     {
00091       this->sync();
00092       // NOTE: We don't do ::close(m_filedes) here since we leave that
00093       // up to whoever instantiated this stdiobuf.
00094       m_filedes = -1;
00095       m_mode = 0;
00096     }
00097 }
00098 
00099 int rutz::stdiobuf::underflow() // with help from Josuttis, p. 678
00100 {
00101 GVX_TRACE("rutz::stdiobuf::underflow");
00102   // is read position before end of buffer?
00103   if (gptr() < egptr())
00104     return *gptr();
00105 
00106   int numPutback = 0;
00107   if (s_pback_size > 0)
00108     {
00109       // process size of putback area
00110       // -use number of characters read
00111       // -but at most four
00112       numPutback = gptr() - eback();
00113       if (numPutback > 4)
00114         numPutback = 4;
00115 
00116       // copy up to four characters previously read into the putback
00117       // buffer (area of first four characters)
00118       std::memcpy (buffer+(4-numPutback), gptr()-numPutback,
00119                    numPutback);
00120     }
00121 
00122   // read new characters
00123   const int num = ::read(m_filedes,
00124                          buffer+s_pback_size,
00125                          s_buf_size-s_pback_size);
00126 
00127   if (num <= 0)
00128     return EOF;
00129 
00130   // reset buffer pointers
00131   setg (buffer+s_pback_size-numPutback,
00132         buffer+s_pback_size,
00133         buffer+s_pback_size+num);
00134 
00135   // return next character Hrmph. We have to cast to unsigned char to
00136   // avoid problems with eof. Problem is, -1 is a valid char value to
00137   // return. However, without a cast, char(-1) (0xff) gets converted
00138   // to int(-1), which is 0xffffffff, which is EOF! What we want is
00139   // int(0x000000ff), which we have to get by int(unsigned char(-1)).
00140   return static_cast<unsigned char>(*gptr());
00141 }
00142 
00143 int rutz::stdiobuf::overflow(int c)
00144 {
00145 GVX_TRACE("rutz::stdiobuf::overflow");
00146   if (!(m_mode & std::ios::out) || !is_open()) return EOF;
00147 
00148   if (c != EOF)
00149     {
00150       // insert the character into the buffer
00151       *pptr() = c;
00152       pbump(1);
00153     }
00154 
00155   if (flushoutput() == EOF)
00156     {
00157       return -1; // ERROR
00158     }
00159 
00160   return c;
00161 }
00162 
00163 int rutz::stdiobuf::sync()
00164 {
00165   if (flushoutput() == EOF)
00166     {
00167       return -1; // ERROR
00168     }
00169   return 0;
00170 }
00171 
00172 int rutz::stdiobuf::flushoutput()
00173 {
00174   if (!(m_mode & std::ios::out) || !is_open()) return EOF;
00175 
00176   const int num = pptr()-pbase();
00177 
00178   if ( ::write(m_filedes, pbase(), num) == -1 )
00179     {
00180       return EOF;
00181     }
00182 
00183   pbump(-num);
00184   return num;
00185 }
00186 
00187 // This is a hack to work around an apparently broken g++ 3.4.3
00188 // on USC's HPCC cluster, in which libstdc++ doesn't include
00189 // instantiations for the constructor and destructor of std::iostream
00190 // (aka std::basic_iostream<char>); so, we force an instantiation of
00191 // those functions here to avoid link errors. This line should be
00192 // quickly removed as soon as we no longer need to use g++ 3.4.3.
00193 #ifdef GVX_MISSING_IOSTREAM_INSTANTIATION
00194 template class std::basic_iostream<char>;
00195 #endif
00196 
00197 static const char __attribute__((used)) vcid_groovx_rutz_stdiobuf_cc_utc20050626084020[] = "$Id: stdiobuf.cc 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/stdiobuf.cc $";
00198 #endif // !GROOVX_RUTZ_STDIOBUF_CC_UTC20050626084020_DEFINED
Generated on Sun May 8 08:42:13 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3