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"
49#include <cstring>
50
51namespace BLOCXX_NAMESPACE
52{
53
54using 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.
69}
70
72TempFileBuffer::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.
85}
86
88void
95void
101void
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.
120 }
121 }
122 }
123 catch(...)
124 {
125 // Ignore?
126 }
127
128 delete [] m_buffer;
129}
131int
133{
134 int cnt = pptr() - pbase();
135 int retval = buffer_to_device(m_buffer, cnt);
137 return retval;
138}
140int
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 {
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);
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}
176std::streamsize
177TempFileBuffer::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}
198int
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}
234int
236{
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}
251int
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}
273int
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}
286std::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}
305void
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);
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}
335void
337{
338 if (m_tempFile)
339 {
341 }
342
343 m_writePos = m_readPos = 0;
344 setg(0,0,0);
346 m_isEOF = false;
347}
348
350String
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
361bool
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
381void
383{
384 m_buffer->rewind();
385 // clear eof bit
386 clear(rdstate() & ~std::ios::eofbit);
387}
389void
391{
392 m_buffer->reset();
393 clear();
394}
396String
398{
399 String rval = m_buffer->releaseFileAndReset();
400 clear();
401 return rval;
402}
404bool
406{
407 return m_buffer->usingTempFile();
408}
409
410} // end namespace BLOCXX_NAMESPACE
411
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
int close()
Close the underlying file object.
Definition File.hpp:171
Int64 seek(Int64 offset, int whence) const
Seek to a given offset within the file.
Definition File.hpp:141
size_t read(void *bfr, size_t numberOfBytes, Int64 offset=-1L) const
Read from the underlying file.
Definition File.hpp:113
Int64 tell() const
Definition File.hpp:149
size_t write(const void *bfr, size_t numberOfBytes, Int64 offset=-1L)
Write to the underlying file.
Definition File.hpp:127
UInt64 size() const
Current size of file.
Definition File.hpp:163
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
String & erase()
Delete all the characters of the string.
Definition String.cpp:824
size_t length() const
Definition String.cpp:354
int buffer_to_device(const char *c, int n)
std::streamsize xsputn(const char *s, std::streamsize n)
void reset()
reset puts this stream object back into its initialized state.
void rewind()
Set the read/write position to the beginning of the data.
TempFileBuffer(size_t bufSize, EKeepFileFlag keepflg=E_DONT_KEEP_FILE)
Create a new TempFileBuffer object.
String releaseFileAndReset()
releaseFileAndReset is like the reset method except it ensures all data has been flused to the underl...
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...
void reset()
reset puts the underlying stream object back into its initialized state.
AutoPtr< TempFileBuffer > m_buffer
TempFileStream(size_t bufSize=4096, TempFileBuffer::EKeepFileFlag keepflg=TempFileBuffer::E_DONT_KEEP_FILE)
Create a new TempFileStream object.
BLOCXX_COMMON_API bool removeFile(const String &path)
Remove the given file.
BLOCXX_COMMON_API File createAutoDeleteTempFile(const String &dir=String())
Create a tempororary file that will be removed when the returned File object is closed.
BLOCXX_COMMON_API File createTempFile(String &filePath, const String &dir=String())
Create a tempororary file in an optional directory.
Taken from RFC 1321.