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
00033
00039
00040
00041
00042
00043
00044 #include "blocxx/BLOCXX_config.h"
00045 #include "blocxx/TempFileStream.hpp"
00046 #include "blocxx/FileSystem.hpp"
00047 #include "blocxx/Assertion.hpp"
00048 #include "blocxx/IOException.hpp"
00049 #include <cstring>
00050
00051 namespace BLOCXX_NAMESPACE
00052 {
00053
00054 using std::iostream;
00056 TempFileBuffer::TempFileBuffer(size_t bufSize, EKeepFileFlag keepflg)
00057 : m_bufSize(bufSize)
00058 , m_buffer(new char[m_bufSize])
00059 , m_tempFile()
00060 , m_readPos(0)
00061 , m_writePos(0)
00062 , m_isEOF(false)
00063 , m_dir()
00064 , m_keepFlag(keepflg)
00065 , m_filePath()
00066 {
00067 setg(0,0,0);
00068 initPutBuffer();
00069 }
00070
00072 TempFileBuffer::TempFileBuffer(const String& dir, size_t bufSize, EKeepFileFlag keepflg)
00073 : m_bufSize(bufSize)
00074 , m_buffer(new char[m_bufSize])
00075 , m_tempFile()
00076 , m_readPos(0)
00077 , m_writePos(0)
00078 , m_isEOF(false)
00079 , m_dir(dir)
00080 , m_keepFlag(keepflg)
00081 , m_filePath()
00082 {
00083 setg(0,0,0);
00084 initPutBuffer();
00085 }
00086
00088 void
00089 TempFileBuffer::initBuffers()
00090 {
00091 initPutBuffer();
00092 initGetBuffer();
00093 }
00095 void
00096 TempFileBuffer::initPutBuffer()
00097 {
00098 setp(m_buffer, m_buffer + m_bufSize);
00099 }
00101 void
00102 TempFileBuffer::initGetBuffer()
00103 {
00104 setg(m_buffer, m_buffer, m_buffer);
00105 }
00107 TempFileBuffer::~TempFileBuffer()
00108 {
00109 try
00110 {
00111 if (m_filePath.length())
00112 {
00113 String fname = releaseFileAndReset();
00114 if (fname.length())
00115 {
00116
00117
00118
00119 FileSystem::removeFile(fname);
00120 }
00121 }
00122 }
00123 catch(...)
00124 {
00125
00126 }
00127
00128 delete [] m_buffer;
00129 }
00131 int
00132 TempFileBuffer::buffer_out()
00133 {
00134 int cnt = pptr() - pbase();
00135 int retval = buffer_to_device(m_buffer, cnt);
00136 initPutBuffer();
00137 return retval;
00138 }
00140 int
00141 TempFileBuffer::overflow(int c)
00142 {
00143 if (pptr())
00144 {
00145 if (buffer_out() < 0)
00146 {
00147 return EOF;
00148 }
00149 }
00150 else
00151 {
00152 if (!m_tempFile)
00153 {
00154 initPutBuffer();
00155 pbump(m_writePos);
00156 m_readPos = gptr() - eback();
00157 }
00158 else
00159 {
00160 m_readPos = m_tempFile.tell() - (egptr() - gptr());
00161 m_tempFile.seek(m_writePos, SEEK_SET);
00162 initPutBuffer();
00163 }
00164 setg(0,0,0);
00165 }
00166 if (c != EOF)
00167 {
00168 return sputc(c);
00169 }
00170 else
00171 {
00172 return c;
00173 }
00174 }
00176 std::streamsize
00177 TempFileBuffer::xsputn(const char* s, std::streamsize n)
00178 {
00179 if (n < epptr() - pptr())
00180 {
00181 memcpy(pptr(), s, n * sizeof(char));
00182 pbump(n);
00183 return n;
00184 }
00185 else
00186 {
00187 for (std::streamsize i = 0; i < n; i++)
00188 {
00189 if (sputc(s[i]) == EOF)
00190 {
00191 return i;
00192 }
00193 }
00194 return n;
00195 }
00196 }
00198 int
00199 TempFileBuffer::underflow()
00200 {
00201 if (m_isEOF)
00202 {
00203 return EOF;
00204 }
00205 if (gptr())
00206 {
00207 if (buffer_in() < 0)
00208 {
00209 return EOF;
00210 }
00211 }
00212 else
00213 {
00214 if (m_tempFile)
00215 {
00216 buffer_out();
00217 m_writePos = m_tempFile.tell();
00218 m_tempFile.seek(m_readPos, SEEK_SET);
00219 if (buffer_in() < 0)
00220 {
00221 return EOF;
00222 }
00223 }
00224 else
00225 {
00226 m_writePos = pptr() - pbase();
00227 setg(m_buffer, m_buffer + m_readPos, pptr());
00228 }
00229 setp(0,0);
00230 }
00231 return static_cast<unsigned char>(*gptr());
00232 }
00234 int
00235 TempFileBuffer::buffer_in()
00236 {
00237 int retval = buffer_from_device(m_buffer, m_bufSize);
00238 if (retval <= 0)
00239 {
00240 setg(0,0,0);
00241 m_isEOF = true;
00242 return -1;
00243 }
00244 else
00245 {
00246 setg(m_buffer, m_buffer, m_buffer + retval);
00247 return retval;
00248 }
00249 }
00251 int
00252 TempFileBuffer::buffer_to_device(const char* c, int n)
00253 {
00254 if (!m_tempFile)
00255 {
00256 if (m_keepFlag == E_KEEP_FILE)
00257 {
00258 m_tempFile = FileSystem::createTempFile(m_filePath, m_dir);
00259 }
00260 else
00261 {
00262 m_tempFile = FileSystem::createAutoDeleteTempFile(m_dir);
00263 }
00264
00265 if (!m_tempFile)
00266 {
00267 BLOCXX_THROW(IOException, "Failed to create temp file");
00268 }
00269 }
00270 return static_cast<int>(m_tempFile.write(c, n));
00271 }
00273 int
00274 TempFileBuffer::buffer_from_device(char* c, int n)
00275 {
00276 if (!m_tempFile)
00277 {
00278 return -1;
00279 }
00280 else
00281 {
00282 return static_cast<int>(m_tempFile.read(c, n));
00283 }
00284 }
00286 std::streamsize
00287 TempFileBuffer::getSize()
00288 {
00289 if (gptr() && !m_tempFile)
00290 {
00291 return egptr() - eback();
00292 }
00293 std::streamsize rval = m_writePos;
00294 if (m_tempFile)
00295 {
00296 rval = m_tempFile.size();
00297 }
00298 if (pptr())
00299 {
00300 rval += pptr() - pbase();
00301 }
00302 return rval;
00303 }
00305 void
00306 TempFileBuffer::rewind()
00307 {
00308 m_readPos = 0;
00309 if (m_tempFile)
00310 {
00311 if (pptr())
00312 {
00313 m_writePos += pptr() - pbase();
00314 buffer_out();
00315 }
00316 m_tempFile.seek(0, SEEK_SET);
00317 initGetBuffer();
00318 }
00319 else
00320 {
00321 if (pptr())
00322 {
00323 m_writePos = pptr() - pbase();
00324 }
00325 else if (gptr())
00326 {
00327 m_writePos = egptr() - eback();
00328 }
00329 setg(m_buffer, m_buffer, m_buffer + m_writePos);
00330 }
00331 setp(0,0);
00332 m_isEOF = false;
00333 }
00335 void
00336 TempFileBuffer::reset()
00337 {
00338 if (m_tempFile)
00339 {
00340 m_tempFile.close();
00341 }
00342
00343 m_writePos = m_readPos = 0;
00344 setg(0,0,0);
00345 initPutBuffer();
00346 m_isEOF = false;
00347 }
00348
00350 String
00351 TempFileBuffer::releaseFileAndReset()
00352 {
00353 buffer_out();
00354 reset();
00355 String rv = m_filePath;
00356 m_filePath.erase();
00357 return rv;
00358 }
00359
00361 bool
00362 TempFileBuffer::usingTempFile() const
00363 {
00364 return bool(m_tempFile);
00365 }
00367 TempFileStream::TempFileStream(size_t bufSize, TempFileBuffer::EKeepFileFlag keepflg)
00368 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(bufSize, keepflg))
00369 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00370 {
00371 }
00372
00374 TempFileStream::TempFileStream(const String& dir, size_t bufSize, TempFileBuffer::EKeepFileFlag keepflg)
00375 : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(dir, bufSize, keepflg))
00376 , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
00377 {
00378 }
00379
00381 void
00382 TempFileStream::rewind()
00383 {
00384 m_buffer->rewind();
00385
00386 clear(rdstate() & ~std::ios::eofbit);
00387 }
00389 void
00390 TempFileStream::reset()
00391 {
00392 m_buffer->reset();
00393 clear();
00394 }
00396 String
00397 TempFileStream::releaseFileAndReset()
00398 {
00399 String rval = m_buffer->releaseFileAndReset();
00400 clear();
00401 return rval;
00402 }
00404 bool
00405 TempFileStream::usingTempFile() const
00406 {
00407 return m_buffer->usingTempFile();
00408 }
00409
00410 }
00411