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
00031
00032
00038
00039
00040
00041
00042
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);
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);
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())
00119 {
00120 if (buffer_out() < 0)
00121 {
00122 return EOF;
00123 }
00124 }
00125 else
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())
00181 {
00182 if (buffer_in() < 0)
00183 {
00184 return EOF;
00185 }
00186 }
00187 else
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();
00313
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
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 }
00367