]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stream.cpp
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"
19 #include <wx/stream.h>
20 #include <wx/datstrm.h>
21 #include <wx/objstrm.h>
27 #define BUF_TEMP_SIZE 10000
29 // ----------------------------------------------------------------------------
31 // ----------------------------------------------------------------------------
33 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
)
34 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
35 m_buffer_size(0), m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
),
36 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
)
40 wxStreamBuffer::wxStreamBuffer(BufMode mode
)
41 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
42 m_buffer_size(0), m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
),
43 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
)
45 m_stream
= new wxStreamBase();
48 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
50 m_buffer_start
= buffer
.m_buffer_start
;
51 m_buffer_end
= buffer
.m_buffer_end
;
52 m_buffer_pos
= buffer
.m_buffer_pos
;
53 m_buffer_size
= buffer
.m_buffer_size
;
54 m_fixed
= buffer
.m_fixed
;
55 m_flushable
= buffer
.m_flushable
;
56 m_stream
= buffer
.m_stream
;
57 m_mode
= buffer
.m_mode
;
59 m_destroystream
= FALSE
;
62 wxStreamBuffer::~wxStreamBuffer()
65 wxDELETEA(m_buffer_start
);
70 size_t wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
)
74 ptrback
= AllocSpaceWBack(bufsize
);
78 memcpy(ptrback
, buf
, bufsize
);
82 bool wxStreamBuffer::WriteBack(char c
)
86 ptrback
= AllocSpaceWBack(1);
94 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
97 wxDELETEA(m_buffer_start
);
98 m_buffer_start
= buffer_start
;
99 m_buffer_end
= buffer_end
;
101 m_buffer_size
= m_buffer_end
-m_buffer_start
;
102 m_destroybuf
= FALSE
;
106 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
110 wxDELETE(m_buffer_start
);
113 m_buffer_start
= NULL
;
120 b_start
= new char[bufsize
];
121 SetBufferIO(b_start
, b_start
+ bufsize
);
125 void wxStreamBuffer::ResetBuffer()
128 m_buffer_pos
= m_buffer_end
;
130 m_buffer_pos
= m_buffer_start
;
133 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
)
137 m_wbacksize
+= needed_size
;
140 temp_b
= (char *)malloc(m_wbacksize
);
142 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
146 return (char *)((size_t)m_wback
+(m_wbacksize
-needed_size
));
149 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
)
151 size_t s_toget
= m_wbacksize
-m_wbackcur
;
156 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
158 m_wbackcur
+= s_toget
;
159 if (m_wbackcur
== m_wbacksize
) {
161 m_wback
= (char *)NULL
;
169 bool wxStreamBuffer::FillBuffer()
173 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
174 m_buffer_end
= m_buffer_start
+count
;
175 m_buffer_pos
= m_buffer_start
;
182 bool wxStreamBuffer::FlushBuffer()
184 size_t count
, current
;
186 if (m_buffer_pos
== m_buffer_start
|| !m_flushable
)
189 current
= m_buffer_pos
-m_buffer_start
;
190 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
191 if (count
!= current
)
193 m_buffer_pos
= m_buffer_start
;
198 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
200 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
205 memcpy(buffer
, m_buffer_pos
, s_toget
);
206 m_buffer_pos
+= s_toget
;
209 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
211 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
213 if (s_toput
< size
&& !m_fixed
) {
214 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
216 m_buffer_size
+= size
;
217 m_buffer_end
= m_buffer_start
+m_buffer_size
;
222 memcpy(m_buffer_pos
, buffer
, s_toput
);
223 m_buffer_pos
+= s_toput
;
226 void wxStreamBuffer::PutChar(char c
)
228 wxASSERT(m_stream
!= NULL
);
230 if (!m_buffer_size
) {
231 m_stream
->OnSysWrite(&c
, 1);
235 if (!GetDataLeft() && !FlushBuffer()) {
236 m_stream
->m_lasterror
= wxStream_EOF
;
241 m_stream
->m_lastcount
= 1;
244 char wxStreamBuffer::GetChar()
248 wxASSERT(m_stream
!= NULL
);
250 if (!m_buffer_size
) {
251 m_stream
->OnSysRead(&c
, 1);
255 if (!GetDataLeft()) {
256 m_stream
->m_lasterror
= wxStream_EOF
;
260 GetFromBuffer(&c
, 1);
261 m_stream
->m_lastcount
= 1;
265 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
267 wxASSERT(m_stream
!= NULL
);
269 // ------------------
270 // Buffering disabled
271 // ------------------
273 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
274 size
-= m_stream
->m_lastcount
;
276 return m_stream
->m_lastcount
;
278 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
280 if (!m_buffer_size
) {
281 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
287 size_t buf_left
, orig_size
= size
;
290 buf_left
= GetDataLeft();
292 // First case: the requested buffer is larger than the stream buffer,
294 if (size
> buf_left
) {
295 GetFromBuffer(buffer
, buf_left
);
297 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
300 if (m_stream
->m_lasterror
== wxStream_NOERROR
)
301 m_stream
->m_lasterror
= wxStream_EOF
;
302 return (m_stream
->m_lastcount
= orig_size
-size
);
306 // Second case: we just copy from the stream buffer.
307 GetFromBuffer(buffer
, size
);
311 return (m_stream
->m_lastcount
+= orig_size
);
314 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
316 char buf
[BUF_TEMP_SIZE
];
317 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
319 while (bytes_read
== BUF_TEMP_SIZE
) {
320 bytes_read
= Read(buf
, bytes_read
);
321 bytes_read
= s_buf
->Write(buf
, bytes_read
);
327 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
329 wxASSERT(m_stream
!= NULL
);
331 // ------------------
332 // Buffering disabled
333 // ------------------
336 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
338 // ------------------
340 // ------------------
342 size_t buf_left
, orig_size
= size
;
345 buf_left
= m_buffer_end
- m_buffer_pos
;
347 // First case: the buffer to write is larger than the stream buffer,
349 if (size
> buf_left
) {
350 PutToBuffer(buffer
, buf_left
);
352 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
354 if (!FlushBuffer()) {
355 if (m_stream
->m_lasterror
== wxStream_NOERROR
)
356 m_stream
->m_lasterror
= wxStream_EOF
;
357 return (m_stream
->m_lastcount
= orig_size
-size
);
360 m_buffer_pos
= m_buffer_start
;
364 // Second case: just copy it in the stream buffer.
365 PutToBuffer(buffer
, size
);
369 return (m_stream
->m_lastcount
= orig_size
);
372 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
374 char buf
[BUF_TEMP_SIZE
];
375 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
;
377 while (bytes_count
== BUF_TEMP_SIZE
) {
378 if (m_stream
->StreamSize() < bytes_count
)
379 bytes_count
= m_stream
->StreamSize();
380 bytes_count
= sbuf
->Read(buf
, bytes_count
);
381 bytes_count
= Write(buf
, bytes_count
);
387 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
389 off_t ret_off
, diff
, last_access
;
391 last_access
= GetLastAccess();
394 diff
= pos
+ GetIntPosition();
395 if (diff
< 0 || diff
> last_access
)
396 return wxInvalidOffset
;
397 SetIntPosition(diff
);
403 // We'll try to compute an internal position later ...
404 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
408 case wxFromCurrent
: {
409 diff
= pos
+ GetIntPosition();
411 if ( (diff
> last_access
) || (diff
< 0) ) {
412 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
416 SetIntPosition(diff
);
421 // Hard to compute: always seek to the requested position.
422 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
426 return wxInvalidOffset
;
429 off_t
wxStreamBuffer::Tell() const
434 pos
= m_stream
->OnSysTell();
435 if (pos
== wxInvalidOffset
)
436 return wxInvalidOffset
;
437 return pos
- GetLastAccess() + GetIntPosition();
439 return GetIntPosition();
442 size_t wxStreamBuffer::GetDataLeft()
444 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
446 return m_buffer_end
-m_buffer_pos
;
449 // ----------------------------------------------------------------------------
451 // ----------------------------------------------------------------------------
453 wxStreamBase::wxStreamBase()
455 m_lasterror
= wxStream_NOERROR
;
459 wxStreamBase::~wxStreamBase()
463 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
468 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
473 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
475 return wxInvalidOffset
;
478 off_t
wxStreamBase::OnSysTell() const
480 return wxInvalidOffset
;
483 // ----------------------------------------------------------------------------
485 // ----------------------------------------------------------------------------
487 wxInputStream::wxInputStream()
490 m_i_destroybuf
= TRUE
;
491 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
494 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
497 m_i_destroybuf
= FALSE
;
498 m_i_streambuf
= buffer
;
501 wxInputStream::~wxInputStream()
504 delete m_i_streambuf
;
507 char wxInputStream::GetC()
510 m_i_streambuf
->Read(&c
, 1);
514 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
516 m_i_streambuf
->Read(buffer
, size
);
517 // wxStreamBuffer sets all variables for us
521 char wxInputStream::Peek()
523 m_i_streambuf
->GetDataLeft();
525 return *(m_i_streambuf
->GetBufferPos());
529 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
531 char buf
[BUF_TEMP_SIZE
];
532 size_t bytes_read
= BUF_TEMP_SIZE
;
534 while (bytes_read
== BUF_TEMP_SIZE
) {
535 bytes_read
= Read(buf
, bytes_read
).LastRead();
536 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
541 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
543 return m_i_streambuf
->Seek(pos
, mode
);
546 off_t
wxInputStream::TellI() const
548 return m_i_streambuf
->Tell();
551 // --------------------
552 // Overloaded operators
553 // --------------------
555 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
557 wxDataInputStream
s(*this);
563 wxInputStream
& wxInputStream::operator>>(char& c
)
569 wxInputStream
& wxInputStream::operator>>(short& i
)
578 wxInputStream
& wxInputStream::operator>>(int& i
)
587 wxInputStream
& wxInputStream::operator>>(long& i
)
589 /* I only implemented a simple integer parser */
592 while (isspace( c
= GetC() ) )
596 if (! (c
== '-' || isdigit(c
)) ) {
597 InputStreamBuffer()->WriteBack(c
);
617 wxInputStream
& wxInputStream::operator>>(double& f
)
619 /* I only implemented a simple float parser */
622 while (isspace( c
= GetC() ) )
626 if (! (c
== '-' || isdigit(c
)) ) {
627 InputStreamBuffer()->WriteBack(c
);
638 f
= f
*10 + (c
- '0');
643 double f_multiplicator
= (double) 0.1;
647 f
+= (c
-'0')*f_multiplicator
;
648 f_multiplicator
/= 10;
659 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
661 wxObjectInputStream
obj_s(*this);
662 obj
= obj_s
.LoadObject();
668 // ----------------------------------------------------------------------------
670 // ----------------------------------------------------------------------------
671 wxOutputStream::wxOutputStream()
674 m_o_destroybuf
= TRUE
;
675 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
678 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
681 m_o_destroybuf
= FALSE
;
682 m_o_streambuf
= buffer
;
685 wxOutputStream::~wxOutputStream()
688 delete m_o_streambuf
;
691 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
693 m_o_streambuf
->Write(buffer
, size
);
697 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
699 stream_in
.Read(*this);
703 off_t
wxOutputStream::TellO() const
705 return m_o_streambuf
->Tell();
708 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
710 return m_o_streambuf
->Seek(pos
, mode
);
713 void wxOutputStream::Sync()
715 m_o_streambuf
->FlushBuffer();
718 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
720 return Write(string
, strlen(string
));
723 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
725 return Write(string
, string
.Len());
728 wxOutputStream
& wxOutputStream::operator<<(char c
)
733 wxOutputStream
& wxOutputStream::operator<<(short i
)
737 strint
.Printf("%i", i
);
738 return Write(strint
, strint
.Len());
741 wxOutputStream
& wxOutputStream::operator<<(int i
)
745 strint
.Printf("%i", i
);
746 return Write(strint
, strint
.Len());
749 wxOutputStream
& wxOutputStream::operator<<(long i
)
753 strlong
.Printf("%i", i
);
754 return Write((const char *)strlong
, strlong
.Len());
757 wxOutputStream
& wxOutputStream::operator<<(double f
)
761 strfloat
.Printf("%f", f
);
762 return Write(strfloat
, strfloat
.Len());
766 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
768 wxObjectOutputStream
obj_s(*this);
769 obj_s
.SaveObject(obj
);
774 // ----------------------------------------------------------------------------
775 // wxFilterInputStream
776 // ----------------------------------------------------------------------------
777 wxFilterInputStream::wxFilterInputStream()
778 : wxInputStream(NULL
)
780 // WARNING streambuf set to NULL !
783 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
784 : wxInputStream(stream
.InputStreamBuffer())
786 m_parent_i_stream
= &stream
;
789 wxFilterInputStream::~wxFilterInputStream()
793 // ----------------------------------------------------------------------------
794 // wxFilterOutputStream
795 // ----------------------------------------------------------------------------
796 wxFilterOutputStream::wxFilterOutputStream()
797 : wxOutputStream(NULL
)
801 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
802 : wxOutputStream(stream
.OutputStreamBuffer())
804 m_parent_o_stream
= &stream
;
807 wxFilterOutputStream::~wxFilterOutputStream()
811 // ----------------------------------------------------------------------------
812 // Some IOManip function
813 // ----------------------------------------------------------------------------
815 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
818 return stream
.Write("\r\n", 2);
820 return stream
.Write("\n", 1);