]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stream.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/stream.cpp
3 // Purpose: wxStream base classes
4 // Author: Guilhem Lavaux
5 // Modified by: VZ (23.11.00) to fix realloc()ing new[]ed memory,
9 // Copyright: (c) Guilhem Lavaux
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
30 #include "wx/stream.h"
37 #include "wx/datstrm.h"
38 #include "wx/textfile.h"
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 // the temporary buffer size used when copying from stream to stream
45 #define BUF_TEMP_SIZE 4096
47 // ============================================================================
49 // ============================================================================
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 void wxStreamBuffer::SetError(wxStreamError err
)
57 if ( m_stream
&& m_stream
->m_lasterror
== wxSTREAM_NO_ERROR
)
58 m_stream
->m_lasterror
= err
;
61 void wxStreamBuffer::InitBuffer()
68 // if we are going to allocate the buffer, we should free it later as well
72 void wxStreamBuffer::Init()
79 wxStreamBuffer::wxStreamBuffer(BufMode mode
)
89 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
)
99 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
101 // doing this has big chances to lead to a crash when the source buffer is
102 // destroyed (otherwise assume the caller knows what he does)
103 wxASSERT_MSG( !buffer
.m_destroybuf
,
104 _T("it's a bad idea to copy this buffer") );
106 m_buffer_start
= buffer
.m_buffer_start
;
107 m_buffer_end
= buffer
.m_buffer_end
;
108 m_buffer_pos
= buffer
.m_buffer_pos
;
109 m_buffer_size
= buffer
.m_buffer_size
;
110 m_fixed
= buffer
.m_fixed
;
111 m_flushable
= buffer
.m_flushable
;
112 m_stream
= buffer
.m_stream
;
113 m_mode
= buffer
.m_mode
;
114 m_destroybuf
= false;
117 void wxStreamBuffer::FreeBuffer()
121 free(m_buffer_start
);
122 m_buffer_start
= NULL
;
126 wxStreamBuffer::~wxStreamBuffer()
131 wxInputStream
*wxStreamBuffer::GetInputStream() const
133 return m_mode
== write
? NULL
: (wxInputStream
*)m_stream
;
136 wxOutputStream
*wxStreamBuffer::GetOutputStream() const
138 return m_mode
== read
? NULL
: (wxOutputStream
*)m_stream
;
141 void wxStreamBuffer::SetBufferIO(void *buffer_start
,
145 SetBufferIO(buffer_start
, (char *)buffer_end
- (char *)buffer_start
,
149 void wxStreamBuffer::SetBufferIO(void *start
,
153 // start by freeing the old buffer
156 m_buffer_start
= (char *)start
;
157 m_buffer_end
= m_buffer_start
+ len
;
161 // if we own it, we free it
162 m_destroybuf
= takeOwnership
;
167 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
171 // this will free the old buffer and allocate the new one
172 SetBufferIO(malloc(bufsize
), bufsize
, true /* take ownership */);
174 else // no buffer size => no buffer
176 // still free the old one
182 void wxStreamBuffer::ResetBuffer()
187 m_stream
->m_lastcount
= 0;
190 m_buffer_pos
= m_mode
== read
&& m_flushable
195 // fill the buffer with as much data as possible (only for read buffers)
196 bool wxStreamBuffer::FillBuffer()
198 wxInputStream
*inStream
= GetInputStream();
200 // It's legal to have no stream, so we don't complain about it just return false
204 size_t count
= inStream
->OnSysRead(m_buffer_start
, m_buffer_size
);
208 m_buffer_end
= m_buffer_start
+ count
;
209 m_buffer_pos
= m_buffer_start
;
214 // write the buffer contents to the stream (only for write buffers)
215 bool wxStreamBuffer::FlushBuffer()
217 wxCHECK_MSG( m_flushable
, false, _T("can't flush this buffer") );
219 // FIXME: what is this check for? (VZ)
220 if ( m_buffer_pos
== m_buffer_start
)
223 wxOutputStream
*outStream
= GetOutputStream();
225 wxCHECK_MSG( outStream
, false, _T("should have a stream in wxStreamBuffer") );
227 size_t current
= m_buffer_pos
- m_buffer_start
;
228 size_t count
= outStream
->OnSysWrite(m_buffer_start
, current
);
229 if ( count
!= current
)
232 m_buffer_pos
= m_buffer_start
;
237 size_t wxStreamBuffer::GetDataLeft()
239 /* Why is this done? RR. */
240 if ( m_buffer_pos
== m_buffer_end
&& m_flushable
)
243 return GetBytesLeft();
246 // copy up to size bytes from our buffer into the provided one
247 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
249 // don't get more bytes than left in the buffer
250 size_t left
= GetBytesLeft();
255 memcpy(buffer
, m_buffer_pos
, size
);
256 m_buffer_pos
+= size
;
259 // copy the contents of the provided buffer into this one
260 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
262 size_t left
= GetBytesLeft();
268 // we can't realloc the buffer, so just copy what we can
273 // realloc the buffer to have enough space for the data
274 size_t delta
= m_buffer_pos
- m_buffer_start
;
276 char *startOld
= m_buffer_start
;
277 m_buffer_size
+= size
;
278 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
);
279 if ( !m_buffer_start
)
281 // don't leak memory if realloc() failed
282 m_buffer_start
= startOld
;
283 m_buffer_size
-= size
;
285 // what else can we do?
289 // adjust the pointers invalidated by realloc()
290 m_buffer_pos
= m_buffer_start
+ delta
;
291 m_buffer_end
= m_buffer_start
+ m_buffer_size
;
295 memcpy(m_buffer_pos
, buffer
, size
);
296 m_buffer_pos
+= size
;
299 void wxStreamBuffer::PutChar(char c
)
301 wxOutputStream
*outStream
= GetOutputStream();
303 wxCHECK_RET( outStream
, _T("should have a stream in wxStreamBuffer") );
305 // if we don't have buffer at all, just forward this call to the stream,
308 outStream
->OnSysWrite(&c
, sizeof(c
));
312 // otherwise check we have enough space left
313 if ( !GetDataLeft() && !FlushBuffer() )
316 SetError(wxSTREAM_WRITE_ERROR
);
320 PutToBuffer(&c
, sizeof(c
));
321 m_stream
->m_lastcount
= 1;
326 char wxStreamBuffer::Peek()
328 wxCHECK_MSG( m_stream
&& HasBuffer(), 0,
329 _T("should have the stream and the buffer in wxStreamBuffer") );
331 if ( !GetDataLeft() )
333 SetError(wxSTREAM_READ_ERROR
);
338 GetFromBuffer(&c
, sizeof(c
));
344 char wxStreamBuffer::GetChar()
346 wxInputStream
*inStream
= GetInputStream();
348 wxCHECK_MSG( inStream
, 0, _T("should have a stream in wxStreamBuffer") );
353 inStream
->OnSysRead(&c
, sizeof(c
));
357 if ( !GetDataLeft() )
359 SetError(wxSTREAM_READ_ERROR
);
364 GetFromBuffer(&c
, sizeof(c
));
365 m_stream
->m_lastcount
= 1;
372 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
374 // lasterror is reset before all new IO calls
381 wxInputStream
*inStream
= GetInputStream();
383 wxCHECK_MSG( inStream
, 0, _T("should have a stream in wxStreamBuffer") );
385 readBytes
= inStream
->OnSysRead(buffer
, size
);
387 else // we have a buffer, use it
389 size_t orig_size
= size
;
393 size_t left
= GetDataLeft();
395 // if the requested number of bytes if greater than the buffer
396 // size, read data in chunks
399 GetFromBuffer(buffer
, left
);
401 buffer
= (char *)buffer
+ left
;
405 SetError(wxSTREAM_EOF
);
409 else // otherwise just do it in one gulp
411 GetFromBuffer(buffer
, size
);
416 readBytes
= orig_size
- size
;
420 m_stream
->m_lastcount
= readBytes
;
425 // this should really be called "Copy()"
426 size_t wxStreamBuffer::Read(wxStreamBuffer
*dbuf
)
428 wxCHECK_MSG( m_mode
!= write
, 0, _T("can't read from this buffer") );
430 char buf
[BUF_TEMP_SIZE
];
436 nRead
= Read(buf
, WXSIZEOF(buf
));
439 nRead
= dbuf
->Write(buf
, nRead
);
448 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
452 // lasterror is reset before all new IO calls
458 if ( !HasBuffer() && m_fixed
)
460 wxOutputStream
*outStream
= GetOutputStream();
462 wxCHECK_MSG( outStream
, 0, _T("should have a stream in wxStreamBuffer") );
464 // no buffer, just forward the call to the stream
465 ret
= outStream
->OnSysWrite(buffer
, size
);
467 else // we [may] have a buffer, use it
469 size_t orig_size
= size
;
473 size_t left
= GetBytesLeft();
475 // if the buffer is too large to fit in the stream buffer, split
476 // it in smaller parts
478 // NB: If stream buffer isn't fixed (as for wxMemoryOutputStream),
479 // we always go to the second case.
481 // FIXME: fine, but if it fails we should (re)try writing it by
482 // chunks as this will (hopefully) always work (VZ)
484 if ( size
> left
&& m_fixed
)
486 PutToBuffer(buffer
, left
);
488 buffer
= (char *)buffer
+ left
;
490 if ( !FlushBuffer() )
492 SetError(wxSTREAM_WRITE_ERROR
);
497 m_buffer_pos
= m_buffer_start
;
499 else // we can do it in one gulp
501 PutToBuffer(buffer
, size
);
506 ret
= orig_size
- size
;
511 // i am not entirely sure what we do this for
512 m_stream
->m_lastcount
= ret
;
518 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
520 wxCHECK_MSG( m_mode
!= read
, 0, _T("can't write to this buffer") );
521 wxCHECK_MSG( sbuf
->m_mode
!= write
, 0, _T("can't read from that buffer") );
523 char buf
[BUF_TEMP_SIZE
];
529 size_t nRead
= sbuf
->Read(buf
, WXSIZEOF(buf
));
532 nWrite
= Write(buf
, nRead
);
533 if ( nWrite
< nRead
)
535 // put back data we couldn't copy
536 wxInputStream
*in_stream
= (wxInputStream
*)sbuf
->GetStream();
538 in_stream
->Ungetch(buf
+ nWrite
, nRead
- nWrite
);
548 while ( nWrite
== WXSIZEOF(buf
) );
553 wxFileOffset
wxStreamBuffer::Seek(wxFileOffset pos
, wxSeekMode mode
)
555 wxFileOffset ret_off
, diff
;
557 wxFileOffset last_access
= GetLastAccess();
568 diff
= pos
+ GetIntPosition();
572 diff
= pos
+ last_access
;
576 wxFAIL_MSG( _T("invalid seek mode") );
578 return wxInvalidOffset
;
580 if (diff
< 0 || diff
> last_access
)
581 return wxInvalidOffset
;
582 size_t int_diff
= wx_truncate_cast(size_t, diff
);
583 wxCHECK_MSG( (wxFileOffset
)int_diff
== diff
, wxInvalidOffset
, wxT("huge file not supported") );
584 SetIntPosition(int_diff
);
591 // We'll try to compute an internal position later ...
592 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
597 diff
= pos
+ GetIntPosition();
599 if ( (diff
> last_access
) || (diff
< 0) )
601 // We must take into account the fact that we have read
602 // something previously.
603 ret_off
= m_stream
->OnSysSeek(diff
-last_access
, wxFromCurrent
);
609 size_t int_diff
= wx_truncate_cast(size_t, diff
);
610 wxCHECK_MSG( (wxFileOffset
)int_diff
== diff
, wxInvalidOffset
, wxT("huge file not supported") );
611 SetIntPosition(int_diff
);
616 // Hard to compute: always seek to the requested position.
617 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
622 return wxInvalidOffset
;
625 wxFileOffset
wxStreamBuffer::Tell() const
629 // ask the stream for position if we have a real one
632 pos
= m_stream
->OnSysTell();
633 if ( pos
== wxInvalidOffset
)
634 return wxInvalidOffset
;
636 else // no associated stream
641 pos
+= GetIntPosition();
643 if ( m_mode
== read
&& m_flushable
)
644 pos
-= GetLastAccess();
649 // ----------------------------------------------------------------------------
651 // ----------------------------------------------------------------------------
653 wxStreamBase::wxStreamBase()
655 m_lasterror
= wxSTREAM_NO_ERROR
;
659 wxStreamBase::~wxStreamBase()
663 size_t wxStreamBase::GetSize() const
665 wxFileOffset length
= GetLength();
666 if ( length
== wxInvalidOffset
)
669 const size_t len
= wx_truncate_cast(size_t, length
);
670 wxASSERT_MSG( len
== length
+ size_t(0), _T("large files not supported") );
675 wxFileOffset
wxStreamBase::OnSysSeek(wxFileOffset
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
677 return wxInvalidOffset
;
680 wxFileOffset
wxStreamBase::OnSysTell() const
682 return wxInvalidOffset
;
685 // ----------------------------------------------------------------------------
687 // ----------------------------------------------------------------------------
689 wxInputStream::wxInputStream()
696 wxInputStream::~wxInputStream()
701 bool wxInputStream::CanRead() const
703 // we don't know if there is anything to read or not and by default we
704 // prefer to be optimistic and try to read data unless we know for sure
705 // there is no more of it
706 return m_lasterror
!= wxSTREAM_EOF
;
709 bool wxInputStream::Eof() const
711 // the only way the base class can know we're at EOF is when we'd already
712 // tried to read beyond it in which case last error is set accordingly
713 return GetLastError() == wxSTREAM_EOF
;
716 char *wxInputStream::AllocSpaceWBack(size_t needed_size
)
718 // get number of bytes left from previous wback buffer
719 size_t toget
= m_wbacksize
- m_wbackcur
;
721 // allocate a buffer large enough to hold prev + new data
722 char *temp_b
= (char *)malloc(needed_size
+ toget
);
727 // copy previous data (and free old buffer) if needed
730 memmove(temp_b
+ needed_size
, m_wback
+ m_wbackcur
, toget
);
737 m_wbacksize
= needed_size
+ toget
;
742 size_t wxInputStream::GetWBack(void *buf
, size_t size
)
747 // how many bytes do we have in the buffer?
748 size_t toget
= m_wbacksize
- m_wbackcur
;
752 // we won't read everything
756 // copy the data from the cache
757 memcpy(buf
, m_wback
+ m_wbackcur
, toget
);
760 if ( m_wbackcur
== m_wbacksize
)
762 // TODO: should we really free it here all the time? maybe keep it?
769 // return the number of bytes copied
773 size_t wxInputStream::Ungetch(const void *buf
, size_t bufsize
)
775 if ( m_lasterror
!= wxSTREAM_NO_ERROR
&& m_lasterror
!= wxSTREAM_EOF
)
777 // can't operate on this stream until the error is cleared
781 char *ptrback
= AllocSpaceWBack(bufsize
);
785 // Eof() shouldn't return true any longer
786 if ( m_lasterror
== wxSTREAM_EOF
)
787 m_lasterror
= wxSTREAM_NO_ERROR
;
789 memcpy(ptrback
, buf
, bufsize
);
793 bool wxInputStream::Ungetch(char c
)
795 return Ungetch(&c
, sizeof(c
)) != 0;
798 char wxInputStream::GetC()
805 wxInputStream
& wxInputStream::Read(void *buf
, size_t size
)
807 char *p
= (char *)buf
;
810 size_t read
= GetWBack(buf
, size
);
819 // we read the requested amount of data
823 if ( p
!= buf
&& !CanRead() )
825 // we have already read something and we would block in OnSysRead()
826 // now: don't do it but return immediately
830 read
= OnSysRead(p
, size
);
833 // no more data available
841 char wxInputStream::Peek()
845 if (m_lasterror
== wxSTREAM_NO_ERROR
)
854 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
856 char buf
[BUF_TEMP_SIZE
];
860 size_t bytes_read
= Read(buf
, WXSIZEOF(buf
)).LastRead();
864 if ( stream_out
.Write(buf
, bytes_read
).LastWrite() != bytes_read
)
871 wxFileOffset
wxInputStream::SeekI(wxFileOffset pos
, wxSeekMode mode
)
873 // RR: This code is duplicated in wxBufferedInputStream. This is
874 // not really a good design, but buffered stream are different
875 // from all other in that they handle two stream-related objects,
876 // the stream buffer and parent stream.
878 // I don't know whether it should be put as well in wxFileInputStream::OnSysSeek
879 if (m_lasterror
==wxSTREAM_EOF
)
880 m_lasterror
=wxSTREAM_NO_ERROR
;
882 /* RR: A call to SeekI() will automatically invalidate any previous
883 call to Ungetch(), otherwise it would be possible to SeekI() to
884 one position, unread some bytes there, SeekI() to another position
885 and the data would be corrupted.
887 GRG: Could add code here to try to navigate within the wback
888 buffer if possible, but is it really needed? It would only work
889 when seeking in wxFromCurrent mode, else it would invalidate
894 wxLogDebug( wxT("Seeking in stream which has data written back to it.") );
902 return OnSysSeek(pos
, mode
);
905 wxFileOffset
wxInputStream::TellI() const
907 wxFileOffset pos
= OnSysTell();
909 if (pos
!= wxInvalidOffset
)
910 pos
-= (m_wbacksize
- m_wbackcur
);
916 // ----------------------------------------------------------------------------
918 // ----------------------------------------------------------------------------
920 wxOutputStream::wxOutputStream()
924 wxOutputStream::~wxOutputStream()
928 size_t wxOutputStream::OnSysWrite(const void * WXUNUSED(buffer
),
929 size_t WXUNUSED(bufsize
))
934 void wxOutputStream::PutC(char c
)
936 Write(&c
, sizeof(c
));
939 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
941 m_lastcount
= OnSysWrite(buffer
, size
);
945 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
947 stream_in
.Read(*this);
951 wxFileOffset
wxOutputStream::TellO() const
956 wxFileOffset
wxOutputStream::SeekO(wxFileOffset pos
, wxSeekMode mode
)
958 return OnSysSeek(pos
, mode
);
961 void wxOutputStream::Sync()
966 // ----------------------------------------------------------------------------
967 // wxCountingOutputStream
968 // ----------------------------------------------------------------------------
970 wxCountingOutputStream::wxCountingOutputStream ()
975 wxFileOffset
wxCountingOutputStream::GetLength() const
980 size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer
),
983 m_currentPos
+= size
;
984 if (m_currentPos
> m_lastcount
)
985 m_lastcount
= m_currentPos
;
990 wxFileOffset
wxCountingOutputStream::OnSysSeek(wxFileOffset pos
, wxSeekMode mode
)
992 ssize_t new_pos
= wx_truncate_cast(ssize_t
, pos
);
997 wxCHECK_MSG( (wxFileOffset
)new_pos
== pos
, wxInvalidOffset
, wxT("huge position not supported") );
1001 new_pos
= m_lastcount
+ new_pos
;
1002 wxCHECK_MSG( (wxFileOffset
)new_pos
== (wxFileOffset
)(m_lastcount
+ pos
), wxInvalidOffset
, wxT("huge position not supported") );
1006 new_pos
= m_currentPos
+ new_pos
;
1007 wxCHECK_MSG( (wxFileOffset
)new_pos
== (wxFileOffset
)(m_currentPos
+ pos
), wxInvalidOffset
, wxT("huge position not supported") );
1011 wxFAIL_MSG( _T("invalid seek mode") );
1012 return wxInvalidOffset
;
1015 m_currentPos
= new_pos
;
1017 if (m_currentPos
> m_lastcount
)
1018 m_lastcount
= m_currentPos
;
1020 return m_currentPos
;
1023 wxFileOffset
wxCountingOutputStream::OnSysTell() const
1025 return m_currentPos
;
1028 // ----------------------------------------------------------------------------
1029 // wxFilterInputStream
1030 // ----------------------------------------------------------------------------
1032 wxFilterInputStream::wxFilterInputStream()
1034 m_parent_i_stream
= NULL
;
1037 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
1039 m_parent_i_stream
= &stream
;
1042 wxFilterInputStream::~wxFilterInputStream()
1046 // ----------------------------------------------------------------------------
1047 // wxFilterOutputStream
1048 // ----------------------------------------------------------------------------
1050 wxFilterOutputStream::wxFilterOutputStream()
1052 m_parent_o_stream
= NULL
;
1055 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
1057 m_parent_o_stream
= &stream
;
1060 wxFilterOutputStream::~wxFilterOutputStream()
1064 // ----------------------------------------------------------------------------
1065 // wxBufferedInputStream
1066 // ----------------------------------------------------------------------------
1068 wxBufferedInputStream::wxBufferedInputStream(wxInputStream
& s
,
1069 wxStreamBuffer
*buffer
)
1070 : wxFilterInputStream(s
)
1074 // use the buffer provided by the user
1075 m_i_streambuf
= buffer
;
1077 else // create a default buffer
1079 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
1081 m_i_streambuf
->SetBufferIO(1024);
1085 wxBufferedInputStream::~wxBufferedInputStream()
1087 m_parent_i_stream
->SeekI(-(wxFileOffset
)m_i_streambuf
->GetBytesLeft(),
1090 delete m_i_streambuf
;
1093 char wxBufferedInputStream::Peek()
1095 return m_i_streambuf
->Peek();
1098 wxInputStream
& wxBufferedInputStream::Read(void *buf
, size_t size
)
1100 // reset the error flag
1103 // first read from the already cached data
1104 m_lastcount
= GetWBack(buf
, size
);
1106 // do we have to read anything more?
1107 if ( m_lastcount
< size
)
1109 size
-= m_lastcount
;
1110 buf
= (char *)buf
+ m_lastcount
;
1112 // the call to wxStreamBuffer::Read() below will reset our m_lastcount,
1114 size_t countOld
= m_lastcount
;
1116 m_i_streambuf
->Read(buf
, size
);
1118 m_lastcount
+= countOld
;
1124 wxFileOffset
wxBufferedInputStream::SeekI(wxFileOffset pos
, wxSeekMode mode
)
1126 // RR: Look at wxInputStream for comments.
1128 if (m_lasterror
==wxSTREAM_EOF
)
1133 wxLogDebug( wxT("Seeking in stream which has data written back to it.") );
1141 return m_i_streambuf
->Seek(pos
, mode
);
1144 wxFileOffset
wxBufferedInputStream::TellI() const
1146 wxFileOffset pos
= m_i_streambuf
->Tell();
1148 if (pos
!= wxInvalidOffset
)
1149 pos
-= (m_wbacksize
- m_wbackcur
);
1154 size_t wxBufferedInputStream::OnSysRead(void *buffer
, size_t bufsize
)
1156 return m_parent_i_stream
->Read(buffer
, bufsize
).LastRead();
1159 wxFileOffset
wxBufferedInputStream::OnSysSeek(wxFileOffset seek
, wxSeekMode mode
)
1161 return m_parent_i_stream
->SeekI(seek
, mode
);
1164 wxFileOffset
wxBufferedInputStream::OnSysTell() const
1166 return m_parent_i_stream
->TellI();
1169 void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer
*buffer
)
1171 wxCHECK_RET( buffer
, _T("wxBufferedInputStream needs buffer") );
1173 delete m_i_streambuf
;
1174 m_i_streambuf
= buffer
;
1177 // ----------------------------------------------------------------------------
1178 // wxBufferedOutputStream
1179 // ----------------------------------------------------------------------------
1181 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream
& s
,
1182 wxStreamBuffer
*buffer
)
1183 : wxFilterOutputStream(s
)
1187 m_o_streambuf
= buffer
;
1189 else // create a default one
1191 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
1193 m_o_streambuf
->SetBufferIO(1024);
1197 wxBufferedOutputStream::~wxBufferedOutputStream()
1200 delete m_o_streambuf
;
1203 bool wxBufferedOutputStream::Close()
1210 wxOutputStream
& wxBufferedOutputStream::Write(const void *buffer
, size_t size
)
1213 m_o_streambuf
->Write(buffer
, size
);
1217 wxFileOffset
wxBufferedOutputStream::SeekO(wxFileOffset pos
, wxSeekMode mode
)
1220 return m_o_streambuf
->Seek(pos
, mode
);
1223 wxFileOffset
wxBufferedOutputStream::TellO() const
1225 return m_o_streambuf
->Tell();
1228 void wxBufferedOutputStream::Sync()
1230 m_o_streambuf
->FlushBuffer();
1231 m_parent_o_stream
->Sync();
1234 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer
, size_t bufsize
)
1236 return m_parent_o_stream
->Write(buffer
, bufsize
).LastWrite();
1239 wxFileOffset
wxBufferedOutputStream::OnSysSeek(wxFileOffset seek
, wxSeekMode mode
)
1241 return m_parent_o_stream
->SeekO(seek
, mode
);
1244 wxFileOffset
wxBufferedOutputStream::OnSysTell() const
1246 return m_parent_o_stream
->TellO();
1249 wxFileOffset
wxBufferedOutputStream::GetLength() const
1251 return m_parent_o_stream
->GetLength() + m_o_streambuf
->GetIntPosition();
1254 void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer
*buffer
)
1256 wxCHECK_RET( buffer
, _T("wxBufferedOutputStream needs buffer") );
1258 delete m_o_streambuf
;
1259 m_o_streambuf
= buffer
;
1262 // ----------------------------------------------------------------------------
1263 // Some IOManip function
1264 // ----------------------------------------------------------------------------
1266 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
1268 static const wxChar
*eol
= wxTextFile::GetEOL();
1270 return stream
.Write(eol
, wxStrlen(eol
));
1273 #endif // wxUSE_STREAMS