TempFileStream.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 // gptr() && !pptr() == input mode
00039 // !gptr() && pptr() == output mode
00040 // pptr() && gptr() should never happen
00041 // !gptr() && !pptr() should never happen
00042 // pptr() should never be 0 unless we're gone to file.
00043 #include "blocxx/BLOCXX_config.h"
00044 #include "blocxx/TempFileStream.hpp"
00045 #include "blocxx/TmpFile.hpp"
00046 #include "blocxx/Assertion.hpp"
00047 #include <cstring>
00048 
00049 namespace BLOCXX_NAMESPACE
00050 {
00051 
00052 using std::iostream;
00054 TempFileBuffer::TempFileBuffer(size_t bufSize)
00055    : m_bufSize(bufSize)
00056    , m_buffer(new char[m_bufSize])
00057    , m_tempFile(NULL)
00058    , m_readPos(0)
00059    , m_writePos(0)
00060    , m_isEOF(false)
00061 {
00062    setg(0,0,0); // start out in output mode.
00063    initPutBuffer();
00064 }
00066 TempFileBuffer::TempFileBuffer(String const& filename, size_t bufSize)
00067    : m_bufSize(bufSize)
00068    , m_buffer(new char[m_bufSize])
00069    , m_tempFile(new TmpFile(filename))
00070    , m_readPos(0)
00071    , m_writePos(0)
00072    , m_isEOF(false)
00073 {
00074    m_tempFile->seek(0, SEEK_END);
00075    m_writePos = m_tempFile->tell();
00076    m_tempFile->rewind();
00077    setp(0,0); // start out in input mode.
00078    initGetBuffer();
00079 }
00081 void
00082 TempFileBuffer::initBuffers()
00083 {
00084    initPutBuffer();
00085    initGetBuffer();
00086 }
00088 void
00089 TempFileBuffer::initPutBuffer()
00090 {
00091    setp(m_buffer, m_buffer + m_bufSize);
00092 }
00094 void
00095 TempFileBuffer::initGetBuffer()
00096 {
00097    setg(m_buffer, m_buffer, m_buffer);
00098 }
00100 TempFileBuffer::~TempFileBuffer()
00101 {
00102    delete [] m_buffer;
00103    delete m_tempFile;
00104 }
00106 int
00107 TempFileBuffer::buffer_out()
00108 {
00109    int cnt = pptr() - pbase();
00110    int retval = buffer_to_device(m_buffer, cnt);
00111    initPutBuffer();
00112    return retval;
00113 }
00115 int
00116 TempFileBuffer::overflow(int c)
00117 {
00118    if (pptr()) // buffer is full
00119    {
00120       if (buffer_out() < 0)
00121       {
00122          return EOF;
00123       }
00124    }
00125    else  // switching from input to output
00126    {
00127       if (!m_tempFile)
00128       {
00129          initPutBuffer();
00130          pbump(m_writePos);
00131          m_readPos = gptr() - eback();
00132       }
00133       else
00134       {
00135          m_readPos = m_tempFile->tell() - (egptr() - gptr());
00136          m_tempFile->seek(m_writePos);
00137          initPutBuffer();
00138       }
00139       setg(0,0,0);
00140    }
00141    if (c != EOF)
00142    {
00143       return sputc(c);
00144    }
00145    else
00146    {
00147       return c;
00148    }
00149 }
00151 std::streamsize
00152 TempFileBuffer::xsputn(const char* s, std::streamsize n)
00153 {
00154    if (n < epptr() - pptr())
00155    {
00156       memcpy(pptr(), s, n * sizeof(char));
00157       pbump(n);
00158       return n;
00159    }
00160    else
00161    {
00162       for (std::streamsize i = 0; i < n; i++)
00163       {
00164          if (sputc(s[i]) == EOF)
00165          {
00166             return i;
00167          }
00168       }
00169       return n;
00170    }
00171 }
00173 int
00174 TempFileBuffer::underflow()
00175 {
00176    if (m_isEOF)
00177    {
00178       return EOF;
00179    }
00180    if (gptr()) // need to fill buffer
00181    {
00182       if (buffer_in() < 0)
00183       {
00184          return EOF;
00185       }
00186    }
00187    else // we're in output mode; switch to input mode
00188    {
00189       if (m_tempFile)
00190       {
00191          buffer_out();
00192          m_writePos = m_tempFile->tell();
00193          m_tempFile->seek(m_readPos);
00194          if (buffer_in() < 0)
00195          {
00196             return EOF;
00197          }
00198       }
00199       else
00200       {
00201          m_writePos = pptr() - pbase();
00202          setg(m_buffer, m_buffer + m_readPos, pptr());
00203       }
00204       setp(0,0);
00205    }
00206    return static_cast<unsigned char>(*gptr());
00207 }
00209 int
00210 TempFileBuffer::buffer_in()
00211 {
00212    int retval = buffer_from_device(m_buffer, m_bufSize);
00213    if (retval <= 0)
00214    {
00215       setg(0,0,0);
00216       m_isEOF = true;
00217       return -1;
00218    }
00219    else
00220    {
00221       setg(m_buffer, m_buffer, m_buffer + retval);
00222       return retval;
00223    }
00224 }
00226 int
00227 TempFileBuffer::buffer_to_device(const char* c, int n)
00228 {
00229    if (!m_tempFile)
00230    {
00231       m_tempFile = new TmpFile;
00232    }
00233    return static_cast<int>(m_tempFile->write(c, n));
00234 }
00236 int
00237 TempFileBuffer::buffer_from_device(char* c, int n)
00238 {
00239    if (!m_tempFile)
00240    {
00241       return -1;
00242    }
00243    else
00244    {
00245       return static_cast<int>(m_tempFile->read(c, n));
00246    }
00247 }
00249 std::streamsize
00250 TempFileBuffer::getSize()
00251 {
00252    if (gptr() && !m_tempFile)
00253    {
00254       return egptr() - eback();
00255    }
00256    std::streamsize rval = m_writePos;
00257    if (m_tempFile)
00258    {
00259       rval = m_tempFile->getSize();
00260    }
00261    if (pptr())
00262    {
00263       rval += pptr() - pbase();
00264    }
00265    return rval;
00266 }
00268 void
00269 TempFileBuffer::rewind()
00270 {
00271    m_readPos = 0;
00272    if (m_tempFile)
00273    {
00274       if (pptr())
00275       {
00276          m_writePos += pptr() - pbase();
00277          buffer_out();
00278       }
00279       m_tempFile->seek(0);
00280       initGetBuffer();
00281    }
00282    else
00283    {
00284       if (pptr())
00285       {
00286          m_writePos = pptr() - pbase();
00287       }
00288       else if (gptr())
00289       {
00290          m_writePos = egptr() - eback();
00291       }
00292       setg(m_buffer, m_buffer, m_buffer + m_writePos);
00293    }
00294    setp(0,0);
00295    m_isEOF = false;
00296 }
00298 void
00299 TempFileBuffer::reset()
00300 {
00301    delete m_tempFile;
00302    m_tempFile = NULL;
00303    m_writePos = m_readPos = 0;
00304    setg(0,0,0);
00305    initPutBuffer();
00306    m_isEOF = false;
00307 }
00309 String
00310 TempFileBuffer::releaseFile()
00311 {
00312    buffer_out();  // Flush the buffer and cause the temp file to be written
00313                // if it's not already being used.
00314    String rval = m_tempFile->releaseFile();
00315    reset();
00316    return rval;
00317 }
00319 bool
00320 TempFileBuffer::usingTempFile() const
00321 {
00322    return m_tempFile != 0;
00323 }
00325 TempFileStream::TempFileStream(size_t bufSize)
00326 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(bufSize))
00327 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00328 {
00329 }
00331 TempFileStream::TempFileStream(String const& filename, size_t bufSize)
00332 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(filename, bufSize))
00333 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00334 {
00335 }
00337 void
00338 TempFileStream::rewind()
00339 {
00340    m_buffer->rewind();
00341    // clear eof bit
00342    clear(rdstate() & ~std::ios::eofbit);
00343 }
00345 void
00346 TempFileStream::reset()
00347 {
00348    m_buffer->reset();
00349    clear();
00350 }
00352 String
00353 TempFileStream::releaseFile()
00354 {
00355    String rval = m_buffer->releaseFile();
00356    clear();
00357    return rval;
00358 }
00360 bool
00361 TempFileStream::usingTempFile() const
00362 {
00363    return m_buffer->usingTempFile();
00364 }
00365 
00366 } // end namespace BLOCXX_NAMESPACE
00367 

Generated on Fri Jun 16 15:39:09 2006 for blocxx by  doxygen 1.4.6