blocxx
TempFileStream.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 // gptr() && !pptr() == input mode
40 // !gptr() && pptr() == output mode
41 // pptr() && gptr() should never happen
42 // !gptr() && !pptr() should never happen
43 // pptr() should never be 0 unless we're gone to file.
44 #include "blocxx/BLOCXX_config.h"
46 #include "blocxx/FileSystem.hpp"
47 #include "blocxx/Assertion.hpp"
48 #include "blocxx/IOException.hpp"
49 #include <cstring>
50 
51 namespace BLOCXX_NAMESPACE
52 {
53 
54 using std::iostream;
57  : m_bufSize(bufSize)
58  , m_buffer(new char[m_bufSize])
59  , m_tempFile()
60  , m_readPos(0)
61  , m_writePos(0)
62  , m_isEOF(false)
63  , m_dir()
64  , m_keepFlag(keepflg)
65  , m_filePath()
66 {
67  setg(0,0,0); // start out in output mode.
68  initPutBuffer();
69 }
70 
72 TempFileBuffer::TempFileBuffer(const String& dir, size_t bufSize, EKeepFileFlag keepflg)
73  : m_bufSize(bufSize)
74  , m_buffer(new char[m_bufSize])
75  , m_tempFile()
76  , m_readPos(0)
77  , m_writePos(0)
78  , m_isEOF(false)
79  , m_dir(dir)
80  , m_keepFlag(keepflg)
81  , m_filePath()
82 {
83  setg(0,0,0); // start out in output mode.
84  initPutBuffer();
85 }
86 
88 void
90 {
91  initPutBuffer();
92  initGetBuffer();
93 }
95 void
97 {
98  setp(m_buffer, m_buffer + m_bufSize);
99 }
101 void
103 {
104  setg(m_buffer, m_buffer, m_buffer);
105 }
108 {
109  try
110  {
111  if (m_filePath.length())
112  {
113  String fname = releaseFileAndReset();
114  if (fname.length())
115  {
116  // At this point we know we have been ask to keep the underlying
117  // file but the user never called releaseFileAndReset, so we'll
118  // attempt to removed that here.
119  FileSystem::removeFile(fname);
120  }
121  }
122  }
123  catch(...)
124  {
125  // Ignore?
126  }
127 
128  delete [] m_buffer;
129 }
131 int
133 {
134  int cnt = pptr() - pbase();
135  int retval = buffer_to_device(m_buffer, cnt);
136  initPutBuffer();
137  return retval;
138 }
140 int
142 {
143  if (pptr()) // buffer is full
144  {
145  if (buffer_out() < 0)
146  {
147  return EOF;
148  }
149  }
150  else // switching from input to output
151  {
152  if (!m_tempFile)
153  {
154  initPutBuffer();
155  pbump(m_writePos);
156  m_readPos = gptr() - eback();
157  }
158  else
159  {
160  m_readPos = m_tempFile.tell() - (egptr() - gptr());
161  m_tempFile.seek(m_writePos, SEEK_SET);
162  initPutBuffer();
163  }
164  setg(0,0,0);
165  }
166  if (c != EOF)
167  {
168  return sputc(c);
169  }
170  else
171  {
172  return c;
173  }
174 }
176 std::streamsize
177 TempFileBuffer::xsputn(const char* s, std::streamsize n)
178 {
179  if (n < epptr() - pptr())
180  {
181  memcpy(pptr(), s, n * sizeof(char));
182  pbump(n);
183  return n;
184  }
185  else
186  {
187  for (std::streamsize i = 0; i < n; i++)
188  {
189  if (sputc(s[i]) == EOF)
190  {
191  return i;
192  }
193  }
194  return n;
195  }
196 }
198 int
200 {
201  if (m_isEOF)
202  {
203  return EOF;
204  }
205  if (gptr()) // need to fill buffer
206  {
207  if (buffer_in() < 0)
208  {
209  return EOF;
210  }
211  }
212  else // we're in output mode; switch to input mode
213  {
214  if (m_tempFile)
215  {
216  buffer_out();
218  m_tempFile.seek(m_readPos, SEEK_SET);
219  if (buffer_in() < 0)
220  {
221  return EOF;
222  }
223  }
224  else
225  {
226  m_writePos = pptr() - pbase();
227  setg(m_buffer, m_buffer + m_readPos, pptr());
228  }
229  setp(0,0);
230  }
231  return static_cast<unsigned char>(*gptr());
232 }
234 int
236 {
237  int retval = buffer_from_device(m_buffer, m_bufSize);
238  if (retval <= 0)
239  {
240  setg(0,0,0);
241  m_isEOF = true;
242  return -1;
243  }
244  else
245  {
246  setg(m_buffer, m_buffer, m_buffer + retval);
247  return retval;
248  }
249 }
251 int
252 TempFileBuffer::buffer_to_device(const char* c, int n)
253 {
254  if (!m_tempFile)
255  {
256  if (m_keepFlag == E_KEEP_FILE)
257  {
259  }
260  else
261  {
263  }
264 
265  if (!m_tempFile)
266  {
267  BLOCXX_THROW(IOException, "Failed to create temp file");
268  }
269  }
270  return static_cast<int>(m_tempFile.write(c, n));
271 }
273 int
275 {
276  if (!m_tempFile)
277  {
278  return -1;
279  }
280  else
281  {
282  return static_cast<int>(m_tempFile.read(c, n));
283  }
284 }
286 std::streamsize
288 {
289  if (gptr() && !m_tempFile)
290  {
291  return egptr() - eback();
292  }
293  std::streamsize rval = m_writePos;
294  if (m_tempFile)
295  {
296  rval = m_tempFile.size();
297  }
298  if (pptr())
299  {
300  rval += pptr() - pbase();
301  }
302  return rval;
303 }
305 void
307 {
308  m_readPos = 0;
309  if (m_tempFile)
310  {
311  if (pptr())
312  {
313  m_writePos += pptr() - pbase();
314  buffer_out();
315  }
316  m_tempFile.seek(0, SEEK_SET);
317  initGetBuffer();
318  }
319  else
320  {
321  if (pptr())
322  {
323  m_writePos = pptr() - pbase();
324  }
325  else if (gptr())
326  {
327  m_writePos = egptr() - eback();
328  }
330  }
331  setp(0,0);
332  m_isEOF = false;
333 }
335 void
337 {
338  if (m_tempFile)
339  {
340  m_tempFile.close();
341  }
342 
343  m_writePos = m_readPos = 0;
344  setg(0,0,0);
345  initPutBuffer();
346  m_isEOF = false;
347 }
348 
350 String
352 {
353  buffer_out(); // Flush the buffer and cause the temp file to be written
354  reset(); // Close file and reset
355  String rv = m_filePath; // Save to return
356  m_filePath.erase(); // Clear filePath to indicate release called
357  return rv;
358 }
359 
361 bool
363 {
364  return bool(m_tempFile);
365 }
368  : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(bufSize, keepflg))
369  , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
370 {
371 }
372 
375  : std::basic_iostream<char, std::char_traits<char> >(new TempFileBuffer(dir, bufSize, keepflg))
376  , m_buffer(dynamic_cast<TempFileBuffer*>(rdbuf()))
377 {
378 }
379 
381 void
383 {
384  m_buffer->rewind();
385  // clear eof bit
386  clear(rdstate() & ~std::ios::eofbit);
387 }
389 void
391 {
392  m_buffer->reset();
393  clear();
394 }
396 String
398 {
399  String rval = m_buffer->releaseFileAndReset();
400  clear();
401  return rval;
402 }
404 bool
406 {
407  return m_buffer->usingTempFile();
408 }
409 
410 } // end namespace BLOCXX_NAMESPACE
411 
TempFileBuffer(size_t bufSize, EKeepFileFlag keepflg=E_DONT_KEEP_FILE)
Create a new TempFileBuffer object.
Int64 seek(Int64 offset, int whence) const
Seek to a given offset within the file.
Definition: File.hpp:141
void reset()
reset puts this stream object back into its initialized state.
Taken from RFC 1321.
UInt64 size() const
Current size of file.
Definition: File.hpp:163
Int64 tell() const
Definition: File.hpp:149
String releaseFileAndReset()
releaseFileAndReset is like the reset method except it ensures all data has been flused to the underl...
void reset()
reset puts the underlying stream object back into its initialized state.
This String class is an abstract data type that represents as NULL terminated string of characters...
Definition: String.hpp:66
void rewind()
Set the read/write position to the beginning of the data.
String releaseFileAndReset()
releaseFileAndReset is like the reset method except it ensures all data has been flused to the underl...
BLOCXX_COMMON_API bool removeFile(const String &path)
Remove the given file.
size_t length() const
Definition: String.cpp:354
int close()
Close the underlying file object.
Definition: File.hpp:171
void rewind()
Set the read/write position to the beginning of the data.
int buffer_from_device(char *c, int n)
String & erase()
Delete all the characters of the string.
Definition: String.cpp:824
int buffer_to_device(const char *c, int n)
AutoPtr< TempFileBuffer > m_buffer
size_t read(void *bfr, size_t numberOfBytes, Int64 offset=-1L) const
Read from the underlying file.
Definition: File.hpp:113
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
Definition: Exception.hpp:263
BLOCXX_COMMON_API File createTempFile(String &filePath, const String &dir=String())
Create a tempororary file in an optional directory.
TempFileStream(size_t bufSize=4096, TempFileBuffer::EKeepFileFlag keepflg=TempFileBuffer::E_DONT_KEEP_FILE)
Create a new TempFileStream object.
std::streamsize xsputn(const char *s, std::streamsize n)
BLOCXX_COMMON_API File createAutoDeleteTempFile(const String &dir=String())
Create a tempororary file that will be removed when the returned File object is closed.
size_t write(const void *bfr, size_t numberOfBytes, Int64 offset=-1L)
Write to the underlying file.
Definition: File.hpp:127