]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stream.cpp
774f0b129b3e6eff63343979fd16f246b007e688
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxStream base classes
4 // Author: Guilhem Lavaux
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "stream.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
30 #include <wx/stream.h>
31 #include <wx/datstrm.h>
32 #include <wx/objstrm.h>
34 #define BUF_TEMP_SIZE 10000
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 #define CHECK_ERROR(err) \
41 if (m_stream->m_lasterror == wxStream_NOERROR) \
42 m_stream->m_lasterror = err
44 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
)
45 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
46 m_buffer_size(0), m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
),
47 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
)
51 wxStreamBuffer::wxStreamBuffer(BufMode mode
)
52 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
53 m_buffer_size(0), m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
),
54 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
)
56 m_stream
= new wxStreamBase();
59 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
61 m_buffer_start
= buffer
.m_buffer_start
;
62 m_buffer_end
= buffer
.m_buffer_end
;
63 m_buffer_pos
= buffer
.m_buffer_pos
;
64 m_buffer_size
= buffer
.m_buffer_size
;
65 m_fixed
= buffer
.m_fixed
;
66 m_flushable
= buffer
.m_flushable
;
67 m_stream
= buffer
.m_stream
;
68 m_mode
= buffer
.m_mode
;
70 m_destroystream
= FALSE
;
73 wxStreamBuffer::~wxStreamBuffer()
76 wxDELETEA(m_buffer_start
);
81 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
84 wxDELETEA(m_buffer_start
);
85 m_buffer_start
= buffer_start
;
86 m_buffer_end
= buffer_end
;
88 m_buffer_size
= m_buffer_end
-m_buffer_start
;
93 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
98 wxDELETEA(m_buffer_start
);
101 m_buffer_start
= NULL
;
108 b_start
= new char[bufsize
];
109 SetBufferIO(b_start
, b_start
+ bufsize
);
113 void wxStreamBuffer::ResetBuffer()
115 m_stream
->m_lasterror
= wxStream_NOERROR
;
116 m_stream
->m_lastcount
= 0;
118 m_buffer_pos
= m_buffer_end
;
120 m_buffer_pos
= m_buffer_start
;
123 bool wxStreamBuffer::FillBuffer()
127 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
128 m_buffer_end
= m_buffer_start
+count
;
129 m_buffer_pos
= m_buffer_start
;
136 bool wxStreamBuffer::FlushBuffer()
138 size_t count
, current
;
140 if (m_buffer_pos
== m_buffer_start
|| !m_flushable
)
143 current
= m_buffer_pos
-m_buffer_start
;
144 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
145 if (count
!= current
)
147 m_buffer_pos
= m_buffer_start
;
152 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
154 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
159 memcpy(buffer
, m_buffer_pos
, s_toget
);
160 m_buffer_pos
+= s_toget
;
163 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
165 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
167 if (s_toput
< size
&& !m_fixed
) {
168 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
170 m_buffer_size
+= size
;
171 m_buffer_end
= m_buffer_start
+m_buffer_size
;
176 memcpy(m_buffer_pos
, buffer
, s_toput
);
177 m_buffer_pos
+= s_toput
;
180 void wxStreamBuffer::PutChar(char c
)
182 wxASSERT(m_stream
!= NULL
);
184 if (!m_buffer_size
) {
185 m_stream
->OnSysWrite(&c
, 1);
189 if (GetDataLeft() == 0 && !FlushBuffer()) {
190 CHECK_ERROR(wxStream_WRITE_ERR
);
195 m_stream
->m_lastcount
= 1;
198 char wxStreamBuffer::GetChar()
202 wxASSERT(m_stream
!= NULL
);
204 if (!m_buffer_size
) {
205 m_stream
->OnSysRead(&c
, 1);
209 if (!GetDataLeft()) {
210 CHECK_ERROR(wxStream_READ_ERR
);
214 GetFromBuffer(&c
, 1);
216 m_stream
->m_lastcount
= 1;
220 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
222 wxASSERT(m_stream
!= NULL
);
227 // ------------------
228 // Buffering disabled
229 // ------------------
231 m_stream
->m_lasterror
= wxStream_NOERROR
;
233 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
238 size_t buf_left
, orig_size
= size
;
241 buf_left
= GetDataLeft();
243 // First case: the requested buffer is larger than the stream buffer,
245 if (size
> buf_left
) {
246 GetFromBuffer(buffer
, buf_left
);
248 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
251 CHECK_ERROR(wxStream_READ_ERR
);
252 return (m_stream
->m_lastcount
= orig_size
-size
);
256 // Second case: we just copy from the stream buffer.
257 GetFromBuffer(buffer
, size
);
261 return (m_stream
->m_lastcount
+= orig_size
);
264 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
266 char buf
[BUF_TEMP_SIZE
];
267 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
272 while (bytes_read
!= 0) {
273 bytes_read
= Read(buf
, bytes_read
);
274 bytes_read
= s_buf
->Write(buf
, bytes_read
);
280 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
282 wxASSERT(m_stream
!= NULL
);
287 // ------------------
288 // Buffering disabled
289 // ------------------
291 m_stream
->m_lasterror
= wxStream_NOERROR
;
293 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
295 // ------------------
297 // ------------------
299 size_t buf_left
, orig_size
= size
;
302 buf_left
= m_buffer_end
- m_buffer_pos
;
304 // First case: the buffer to write is larger than the stream buffer,
306 if (size
> buf_left
) {
307 PutToBuffer(buffer
, buf_left
);
309 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
311 if (!FlushBuffer()) {
312 CHECK_ERROR(wxStream_WRITE_ERR
);
313 return (m_stream
->m_lastcount
= orig_size
-size
);
316 m_buffer_pos
= m_buffer_start
;
320 // Second case: just copy it in the stream buffer.
321 PutToBuffer(buffer
, size
);
325 return (m_stream
->m_lastcount
= orig_size
);
328 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
330 char buf
[BUF_TEMP_SIZE
];
331 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
, b_count2
;
332 wxInputStream
*in_stream
;
337 in_stream
= (wxInputStream
*)sbuf
->Stream();
339 while (bytes_count
== BUF_TEMP_SIZE
) {
340 b_count2
= sbuf
->Read(buf
, bytes_count
);
341 bytes_count
= Write(buf
, b_count2
);
342 if (b_count2
> bytes_count
)
343 in_stream
->Ungetch(buf
+bytes_count
, b_count2
-bytes_count
);
349 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
351 off_t ret_off
, diff
, last_access
;
353 last_access
= GetLastAccess();
356 diff
= pos
+ GetIntPosition();
357 if (diff
< 0 || diff
> last_access
)
358 return wxInvalidOffset
;
359 SetIntPosition(diff
);
365 // We'll try to compute an internal position later ...
366 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
370 case wxFromCurrent
: {
371 diff
= pos
+ GetIntPosition();
373 if ( (diff
> last_access
) || (diff
< 0) ) {
374 // We must take into account the fact that we have read something
377 ret_off
= m_stream
->OnSysSeek(-(last_access
-diff
), wxFromCurrent
);
378 // lastaccess + abs(diff) = lastaccess - diff here
380 ret_off
= m_stream
->OnSysSeek(diff
-last_access
, wxFromCurrent
);
384 SetIntPosition(diff
);
389 // Hard to compute: always seek to the requested position.
390 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
394 return wxInvalidOffset
;
397 off_t
wxStreamBuffer::Tell() const
402 pos
= m_stream
->OnSysTell();
403 if (pos
== wxInvalidOffset
)
404 return wxInvalidOffset
;
405 return pos
- GetLastAccess() + GetIntPosition();
407 return GetIntPosition();
410 size_t wxStreamBuffer::GetDataLeft()
412 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
414 return m_buffer_end
-m_buffer_pos
;
417 // ----------------------------------------------------------------------------
419 // ----------------------------------------------------------------------------
421 wxStreamBase::wxStreamBase()
423 m_lasterror
= wxStream_NOERROR
;
427 wxStreamBase::~wxStreamBase()
431 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
436 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
441 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
443 return wxInvalidOffset
;
446 off_t
wxStreamBase::OnSysTell() const
448 return wxInvalidOffset
;
451 // ----------------------------------------------------------------------------
453 // ----------------------------------------------------------------------------
455 wxInputStream::wxInputStream()
457 m_wback(NULL
), m_wbacksize(0), m_wbackcur(0)
461 wxInputStream::~wxInputStream()
467 char *wxInputStream::AllocSpaceWBack(size_t needed_size
)
471 m_wbacksize
+= needed_size
;
474 temp_b
= (char *)malloc(m_wbacksize
);
476 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
482 return (char *)(m_wback
+(m_wbacksize
-needed_size
));
485 size_t wxInputStream::GetWBack(char *buf
, size_t bsize
)
487 size_t s_toget
= m_wbacksize
-m_wbackcur
;
495 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
497 m_wbackcur
+= s_toget
;
498 if (m_wbackcur
== m_wbacksize
) {
500 m_wback
= (char *)NULL
;
508 size_t wxInputStream::Ungetch(const void *buf
, size_t bufsize
)
512 ptrback
= AllocSpaceWBack(bufsize
);
516 memcpy(ptrback
, buf
, bufsize
);
520 bool wxInputStream::Ungetch(char c
)
524 ptrback
= AllocSpaceWBack(1);
532 char wxInputStream::GetC()
539 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
542 char *buf
= (char *)buffer
;
544 retsize
= GetWBack(buf
, size
);
545 if (retsize
== size
) {
547 m_lasterror
= wxStream_NOERROR
;
553 m_lastcount
= OnSysRead(buf
, size
);
557 char wxInputStream::Peek()
562 if (m_lasterror
== wxStream_NOERROR
) {
569 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
571 char buf
[BUF_TEMP_SIZE
];
572 size_t bytes_read
= BUF_TEMP_SIZE
;
574 while (bytes_read
== BUF_TEMP_SIZE
) {
575 bytes_read
= Read(buf
, bytes_read
).LastRead();
576 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
581 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
583 return OnSysSeek(pos
, mode
);
586 off_t
wxInputStream::TellI() const
591 // --------------------
592 // Overloaded operators
593 // --------------------
596 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
598 wxObjectInputStream
obj_s(*this);
599 obj
= obj_s
.LoadObject();
605 // ----------------------------------------------------------------------------
607 // ----------------------------------------------------------------------------
608 wxOutputStream::wxOutputStream()
613 wxOutputStream::~wxOutputStream()
617 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
619 m_lastcount
= OnSysWrite(buffer
, size
);
623 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
625 stream_in
.Read(*this);
629 off_t
wxOutputStream::TellO() const
634 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
636 return OnSysSeek(pos
, mode
);
639 void wxOutputStream::Sync()
644 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
646 wxObjectOutputStream
obj_s(*this);
647 obj_s
.SaveObject(obj
);
652 // ----------------------------------------------------------------------------
653 // wxFilterInputStream
654 // ----------------------------------------------------------------------------
655 wxFilterInputStream::wxFilterInputStream()
660 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
663 m_parent_i_stream
= &stream
;
666 wxFilterInputStream::~wxFilterInputStream()
670 // ----------------------------------------------------------------------------
671 // wxFilterOutputStream
672 // ----------------------------------------------------------------------------
673 wxFilterOutputStream::wxFilterOutputStream()
678 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
681 m_parent_o_stream
= &stream
;
684 wxFilterOutputStream::~wxFilterOutputStream()
688 // ----------------------------------------------------------------------------
689 // wxBufferedInputStream
690 // ----------------------------------------------------------------------------
691 wxBufferedInputStream::wxBufferedInputStream(wxInputStream
& s
)
692 : wxFilterInputStream(s
)
694 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
695 m_i_streambuf
->SetBufferIO(1024);
698 wxBufferedInputStream::~wxBufferedInputStream()
700 delete m_i_streambuf
;
703 wxInputStream
& wxBufferedInputStream::Read(void *buffer
, size_t size
)
706 char *buf
= (char *)buffer
;
708 retsize
= GetWBack(buf
, size
);
709 m_lastcount
= retsize
;
710 if (retsize
== size
) {
711 m_lasterror
= wxStream_NOERROR
;
717 m_i_streambuf
->Read(buf
, size
);
722 off_t
wxBufferedInputStream::SeekI(off_t pos
, wxSeekMode mode
)
724 return m_i_streambuf
->Seek(pos
, mode
);
727 off_t
wxBufferedInputStream::TellI() const
729 return m_i_streambuf
->Tell();
732 size_t wxBufferedInputStream::OnSysRead(void *buffer
, size_t bufsize
)
734 return m_parent_i_stream
->Read(buffer
, bufsize
).LastRead();
737 off_t
wxBufferedInputStream::OnSysSeek(off_t seek
, wxSeekMode mode
)
739 return m_parent_i_stream
->SeekI(seek
, mode
);
742 off_t
wxBufferedInputStream::OnSysTell() const
744 return m_parent_i_stream
->TellI();
747 // ----------------------------------------------------------------------------
748 // wxBufferedOutputStream
749 // ----------------------------------------------------------------------------
751 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream
& s
)
752 : wxFilterOutputStream(s
)
754 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
755 m_o_streambuf
->SetBufferIO(1024);
758 wxBufferedOutputStream::~wxBufferedOutputStream()
760 delete m_o_streambuf
;
763 wxOutputStream
& wxBufferedOutputStream::Write(const void *buffer
, size_t size
)
766 m_o_streambuf
->Write(buffer
, size
);
770 off_t
wxBufferedOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
772 return m_o_streambuf
->Seek(pos
, mode
);
775 off_t
wxBufferedOutputStream::TellO() const
777 return m_o_streambuf
->Tell();
780 void wxBufferedOutputStream::Sync()
782 m_o_streambuf
->FlushBuffer();
783 m_parent_o_stream
->Sync();
786 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer
, size_t bufsize
)
788 return m_parent_o_stream
->Write(buffer
, bufsize
).LastWrite();
791 off_t
wxBufferedOutputStream::OnSysSeek(off_t seek
, wxSeekMode mode
)
793 return m_parent_o_stream
->SeekO(seek
, mode
);
796 off_t
wxBufferedOutputStream::OnSysTell() const
798 return m_parent_o_stream
->TellO();
801 // ----------------------------------------------------------------------------
802 // Some IOManip function
803 // ----------------------------------------------------------------------------
805 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
808 return stream
.Write("\r\n", 2);
811 return stream
.Write("\r", 1);
813 return stream
.Write("\n", 1);