00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00036
00037
00038
00039
00040
00041 #include "OW_config.h"
00042 #include "OW_TempFileStream.hpp"
00043 #include "OW_TmpFile.hpp"
00044 #include "OW_Assertion.hpp"
00045 #include <cstring>
00046
00047 namespace OW_NAMESPACE
00048 {
00049
00050 using std::iostream;
00052 TempFileBuffer::TempFileBuffer(size_t bufSize)
00053 : m_bufSize(bufSize)
00054 , m_buffer(new char[m_bufSize])
00055 , m_tempFile(NULL)
00056 , m_readPos(0)
00057 , m_writePos(0)
00058 , m_isEOF(false)
00059 {
00060 setg(0,0,0);
00061 initPutBuffer();
00062 }
00064 TempFileBuffer::TempFileBuffer(String const& filename, size_t bufSize)
00065 : m_bufSize(bufSize)
00066 , m_buffer(new char[m_bufSize])
00067 , m_tempFile(new TmpFile(filename))
00068 , m_readPos(0)
00069 , m_writePos(0)
00070 , m_isEOF(false)
00071 {
00072 m_tempFile->seek(0, SEEK_END);
00073 m_writePos = m_tempFile->tell();
00074 m_tempFile->rewind();
00075 setp(0,0);
00076 initGetBuffer();
00077 }
00079 void
00080 TempFileBuffer::initBuffers()
00081 {
00082 initPutBuffer();
00083 initGetBuffer();
00084 }
00086 void
00087 TempFileBuffer::initPutBuffer()
00088 {
00089 setp(m_buffer, m_buffer + m_bufSize);
00090 }
00092 void
00093 TempFileBuffer::initGetBuffer()
00094 {
00095 setg(m_buffer, m_buffer, m_buffer);
00096 }
00098 TempFileBuffer::~TempFileBuffer()
00099 {
00100 delete [] m_buffer;
00101 delete m_tempFile;
00102 }
00104 int
00105 TempFileBuffer::buffer_out()
00106 {
00107 int cnt = pptr() - pbase();
00108 int retval = buffer_to_device(m_buffer, cnt);
00109 initPutBuffer();
00110 return retval;
00111 }
00113 int
00114 TempFileBuffer::overflow(int c)
00115 {
00116 if (pptr())
00117 {
00118 if (buffer_out() < 0)
00119 {
00120 return EOF;
00121 }
00122 }
00123 else
00124 {
00125 if (!m_tempFile)
00126 {
00127 initPutBuffer();
00128 pbump(m_writePos);
00129 m_readPos = gptr() - eback();
00130 }
00131 else
00132 {
00133 m_readPos = m_tempFile->tell() - (egptr() - gptr());
00134 m_tempFile->seek(m_writePos);
00135 initPutBuffer();
00136 }
00137 setg(0,0,0);
00138 }
00139 if (c != EOF)
00140 {
00141 return sputc(c);
00142 }
00143 else
00144 {
00145 return c;
00146 }
00147 }
00149 std::streamsize
00150 TempFileBuffer::xsputn(const char* s, std::streamsize n)
00151 {
00152 if (n < epptr() - pptr())
00153 {
00154 memcpy(pptr(), s, n * sizeof(char));
00155 pbump(n);
00156 return n;
00157 }
00158 else
00159 {
00160 for (std::streamsize i = 0; i < n; i++)
00161 {
00162 if (sputc(s[i]) == EOF)
00163 {
00164 return i;
00165 }
00166 }
00167 return n;
00168 }
00169 }
00171 int
00172 TempFileBuffer::underflow()
00173 {
00174 if (m_isEOF)
00175 {
00176 return EOF;
00177 }
00178 if (gptr())
00179 {
00180 if (buffer_in() < 0)
00181 {
00182 return EOF;
00183 }
00184 }
00185 else
00186 {
00187 if (m_tempFile)
00188 {
00189 buffer_out();
00190 m_writePos = m_tempFile->tell();
00191 m_tempFile->seek(m_readPos);
00192 if (buffer_in() < 0)
00193 {
00194 return EOF;
00195 }
00196 }
00197 else
00198 {
00199 m_writePos = pptr() - pbase();
00200 setg(m_buffer, m_buffer + m_readPos, pptr());
00201 }
00202 setp(0,0);
00203 }
00204 return static_cast<unsigned char>(*gptr());
00205 }
00207 int
00208 TempFileBuffer::buffer_in()
00209 {
00210 int retval = buffer_from_device(m_buffer, m_bufSize);
00211 if (retval <= 0)
00212 {
00213 setg(0,0,0);
00214 m_isEOF = true;
00215 return -1;
00216 }
00217 else
00218 {
00219 setg(m_buffer, m_buffer, m_buffer + retval);
00220 return retval;
00221 }
00222 }
00224 int
00225 TempFileBuffer::buffer_to_device(const char* c, int n)
00226 {
00227 if (!m_tempFile)
00228 {
00229 m_tempFile = new TmpFile;
00230 }
00231 return static_cast<int>(m_tempFile->write(c, n));
00232 }
00234 int
00235 TempFileBuffer::buffer_from_device(char* c, int n)
00236 {
00237 if (!m_tempFile)
00238 {
00239 return -1;
00240 }
00241 else
00242 {
00243 return static_cast<int>(m_tempFile->read(c, n));
00244 }
00245 }
00247 std::streamsize
00248 TempFileBuffer::getSize()
00249 {
00250 if (gptr() && !m_tempFile)
00251 {
00252 return egptr() - eback();
00253 }
00254 std::streamsize rval = m_writePos;
00255 if (m_tempFile)
00256 {
00257 rval = m_tempFile->getSize();
00258 }
00259 if (pptr())
00260 {
00261 rval += pptr() - pbase();
00262 }
00263 return rval;
00264 }
00266 void
00267 TempFileBuffer::rewind()
00268 {
00269 m_readPos = 0;
00270 if (m_tempFile)
00271 {
00272 if (pptr())
00273 {
00274 m_writePos += pptr() - pbase();
00275 buffer_out();
00276 }
00277 m_tempFile->seek(0);
00278 initGetBuffer();
00279 }
00280 else
00281 {
00282 if (pptr())
00283 {
00284 m_writePos = pptr() - pbase();
00285 }
00286 else if (gptr())
00287 {
00288 m_writePos = egptr() - eback();
00289 }
00290 setg(m_buffer, m_buffer, m_buffer + m_writePos);
00291 }
00292 setp(0,0);
00293 m_isEOF = false;
00294 }
00296 void
00297 TempFileBuffer::reset()
00298 {
00299 delete m_tempFile;
00300 m_tempFile = NULL;
00301 m_writePos = m_readPos = 0;
00302 setg(0,0,0);
00303 initPutBuffer();
00304 m_isEOF = false;
00305 }
00307 String
00308 TempFileBuffer::releaseFile()
00309 {
00310 buffer_out();
00311
00312 String rval = m_tempFile->releaseFile();
00313 reset();
00314 return rval;
00315 }
00317 bool
00318 TempFileBuffer::usingTempFile() const
00319 {
00320 return m_tempFile != 0;
00321 }
00323 TempFileStream::TempFileStream(size_t bufSize)
00324 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(bufSize))
00325 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00326 {
00327 }
00329 TempFileStream::TempFileStream(String const& filename, size_t bufSize)
00330 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(filename, bufSize))
00331 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00332 {
00333 }
00335 void
00336 TempFileStream::rewind()
00337 {
00338 m_buffer->rewind();
00339
00340 clear(rdstate() & ~std::ios::eofbit);
00341 }
00343 void
00344 TempFileStream::reset()
00345 {
00346 m_buffer->reset();
00347 clear();
00348 }
00350 String
00351 TempFileStream::releaseFile()
00352 {
00353 String rval = m_buffer->releaseFile();
00354 clear();
00355 return rval;
00356 }
00358 bool
00359 TempFileStream::usingTempFile() const
00360 {
00361 return m_buffer->usingTempFile();
00362 }
00363
00364 }
00365