]>
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"
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_wback(NULL
), m_wbacksize(0), m_wbackcur(0),
47 m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
),
48 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
)
52 wxStreamBuffer::wxStreamBuffer(BufMode mode
)
53 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
54 m_buffer_size(0), m_wback(NULL
), m_wbacksize(0), m_wbackcur(0),
55 m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
),
56 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
)
58 m_stream
= new wxStreamBase();
61 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
63 m_buffer_start
= buffer
.m_buffer_start
;
64 m_buffer_end
= buffer
.m_buffer_end
;
65 m_buffer_pos
= buffer
.m_buffer_pos
;
66 m_buffer_size
= buffer
.m_buffer_size
;
67 m_fixed
= buffer
.m_fixed
;
68 m_flushable
= buffer
.m_flushable
;
69 m_stream
= buffer
.m_stream
;
70 m_mode
= buffer
.m_mode
;
72 m_destroystream
= FALSE
;
78 wxStreamBuffer::~wxStreamBuffer()
83 wxDELETEA(m_buffer_start
);
88 size_t wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
)
95 ptrback
= AllocSpaceWBack(bufsize
);
99 memcpy(ptrback
, buf
, bufsize
);
103 bool wxStreamBuffer::WriteBack(char c
)
107 ptrback
= AllocSpaceWBack(1);
115 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
118 wxDELETEA(m_buffer_start
);
119 m_buffer_start
= buffer_start
;
120 m_buffer_end
= buffer_end
;
122 m_buffer_size
= m_buffer_end
-m_buffer_start
;
123 m_destroybuf
= FALSE
;
127 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
132 wxDELETEA(m_buffer_start
);
135 m_buffer_start
= NULL
;
142 b_start
= new char[bufsize
];
143 SetBufferIO(b_start
, b_start
+ bufsize
);
147 void wxStreamBuffer::ResetBuffer()
149 m_stream
->m_lasterror
= wxStream_NOERROR
;
150 m_stream
->m_lastcount
= 0;
152 m_buffer_pos
= m_buffer_end
;
154 m_buffer_pos
= m_buffer_start
;
157 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
)
161 m_wbacksize
+= needed_size
;
164 temp_b
= (char *)malloc(m_wbacksize
);
166 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
172 return (char *)(m_wback
+(m_wbacksize
-needed_size
));
175 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
)
177 size_t s_toget
= m_wbacksize
-m_wbackcur
;
182 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
184 m_wbackcur
+= s_toget
;
185 if (m_wbackcur
== m_wbacksize
) {
187 m_wback
= (char *)NULL
;
195 bool wxStreamBuffer::FillBuffer()
199 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
200 m_buffer_end
= m_buffer_start
+count
;
201 m_buffer_pos
= m_buffer_start
;
208 bool wxStreamBuffer::FlushBuffer()
210 size_t count
, current
;
212 if (m_buffer_pos
== m_buffer_start
|| !m_flushable
)
215 current
= m_buffer_pos
-m_buffer_start
;
216 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
217 if (count
!= current
)
219 m_buffer_pos
= m_buffer_start
;
224 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
226 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
231 memcpy(buffer
, m_buffer_pos
, s_toget
);
232 m_buffer_pos
+= s_toget
;
235 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
237 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
239 if (s_toput
< size
&& !m_fixed
) {
240 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
242 m_buffer_size
+= size
;
243 m_buffer_end
= m_buffer_start
+m_buffer_size
;
248 memcpy(m_buffer_pos
, buffer
, s_toput
);
249 m_buffer_pos
+= s_toput
;
252 void wxStreamBuffer::PutChar(char c
)
254 wxASSERT(m_stream
!= NULL
);
256 if (!m_buffer_size
) {
257 m_stream
->OnSysWrite(&c
, 1);
261 if (GetDataLeft() == 0 && !FlushBuffer()) {
262 CHECK_ERROR(wxStream_WRITE_ERR
);
267 m_stream
->m_lastcount
= 1;
270 char wxStreamBuffer::GetChar()
274 wxASSERT(m_stream
!= NULL
);
276 if (!m_buffer_size
) {
277 m_stream
->OnSysRead(&c
, 1);
281 if (!GetDataLeft()) {
282 CHECK_ERROR(wxStream_READ_ERR
);
286 GetFromBuffer(&c
, 1);
288 m_stream
->m_lastcount
= 1;
292 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
294 wxASSERT(m_stream
!= NULL
);
299 // ------------------
300 // Buffering disabled
301 // ------------------
303 m_stream
->m_lasterror
= wxStream_NOERROR
;
304 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
305 size
-= m_stream
->m_lastcount
;
307 return m_stream
->m_lastcount
;
309 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
312 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
317 size_t buf_left
, orig_size
= size
;
320 buf_left
= GetDataLeft();
322 // First case: the requested buffer is larger than the stream buffer,
324 if (size
> buf_left
) {
325 GetFromBuffer(buffer
, buf_left
);
327 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
330 CHECK_ERROR(wxStream_READ_ERR
);
331 return (m_stream
->m_lastcount
= orig_size
-size
);
335 // Second case: we just copy from the stream buffer.
336 GetFromBuffer(buffer
, size
);
340 return (m_stream
->m_lastcount
+= orig_size
);
343 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
345 char buf
[BUF_TEMP_SIZE
];
346 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
351 while (bytes_read
!= 0) {
352 bytes_read
= Read(buf
, bytes_read
);
353 bytes_read
= s_buf
->Write(buf
, bytes_read
);
359 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
361 wxASSERT(m_stream
!= NULL
);
366 // ------------------
367 // Buffering disabled
368 // ------------------
370 m_stream
->m_lasterror
= wxStream_NOERROR
;
372 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
374 // ------------------
376 // ------------------
378 size_t buf_left
, orig_size
= size
;
381 buf_left
= m_buffer_end
- m_buffer_pos
;
383 // First case: the buffer to write is larger than the stream buffer,
385 if (size
> buf_left
) {
386 PutToBuffer(buffer
, buf_left
);
388 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
390 if (!FlushBuffer()) {
391 CHECK_ERROR(wxStream_WRITE_ERR
);
392 return (m_stream
->m_lastcount
= orig_size
-size
);
395 m_buffer_pos
= m_buffer_start
;
399 // Second case: just copy it in the stream buffer.
400 PutToBuffer(buffer
, size
);
404 return (m_stream
->m_lastcount
= orig_size
);
407 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
409 char buf
[BUF_TEMP_SIZE
];
410 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
, b_count2
;
415 while (bytes_count
== BUF_TEMP_SIZE
) {
416 b_count2
= sbuf
->Read(buf
, bytes_count
);
417 bytes_count
= Write(buf
, b_count2
);
418 if (b_count2
> bytes_count
)
419 sbuf
->WriteBack(buf
+bytes_count
, b_count2
-bytes_count
);
425 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
427 off_t ret_off
, diff
, last_access
;
429 last_access
= GetLastAccess();
432 diff
= pos
+ GetIntPosition();
433 if (diff
< 0 || diff
> last_access
)
434 return wxInvalidOffset
;
435 SetIntPosition(diff
);
441 // We'll try to compute an internal position later ...
442 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
446 case wxFromCurrent
: {
447 diff
= pos
+ GetIntPosition();
449 if ( (diff
> last_access
) || (diff
< 0) ) {
450 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
454 SetIntPosition(diff
);
459 // Hard to compute: always seek to the requested position.
460 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
464 return wxInvalidOffset
;
467 off_t
wxStreamBuffer::Tell() const
472 pos
= m_stream
->OnSysTell();
473 if (pos
== wxInvalidOffset
)
474 return wxInvalidOffset
;
475 return pos
- GetLastAccess() + GetIntPosition();
477 return GetIntPosition();
480 size_t wxStreamBuffer::GetDataLeft()
482 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
484 return m_buffer_end
-m_buffer_pos
;
487 // ----------------------------------------------------------------------------
489 // ----------------------------------------------------------------------------
491 wxStreamBase::wxStreamBase()
493 m_lasterror
= wxStream_NOERROR
;
497 wxStreamBase::~wxStreamBase()
501 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
506 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
511 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
513 return wxInvalidOffset
;
516 off_t
wxStreamBase::OnSysTell() const
518 return wxInvalidOffset
;
521 // ----------------------------------------------------------------------------
523 // ----------------------------------------------------------------------------
525 wxInputStream::wxInputStream()
528 m_i_destroybuf
= TRUE
;
529 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
532 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
535 m_i_destroybuf
= FALSE
;
536 m_i_streambuf
= buffer
;
539 wxInputStream::~wxInputStream()
542 delete m_i_streambuf
;
545 char wxInputStream::GetC()
548 m_i_streambuf
->Read(&c
, 1);
552 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
554 m_i_streambuf
->Read(buffer
, size
);
555 // wxStreamBuffer sets all variables for us
559 char wxInputStream::Peek()
561 m_i_streambuf
->GetDataLeft();
563 return *(m_i_streambuf
->GetBufferPos());
567 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
569 char buf
[BUF_TEMP_SIZE
];
570 size_t bytes_read
= BUF_TEMP_SIZE
;
572 while (bytes_read
== BUF_TEMP_SIZE
) {
573 bytes_read
= Read(buf
, bytes_read
).LastRead();
574 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
579 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
581 return m_i_streambuf
->Seek(pos
, mode
);
584 off_t
wxInputStream::TellI() const
586 return m_i_streambuf
->Tell();
589 // --------------------
590 // Overloaded operators
591 // --------------------
593 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
595 wxDataInputStream
s(*this);
601 wxInputStream
& wxInputStream::operator>>(char& c
)
607 wxInputStream
& wxInputStream::operator>>(signed short& i
)
616 wxInputStream
& wxInputStream::operator>>(signed int& i
)
625 wxInputStream
& wxInputStream::operator>>(signed long& i
)
627 /* I only implemented a simple integer parser */
631 while (isspace( c
= GetC() ) )
635 if (! (c
== '-' || isdigit(c
)) ) {
636 InputStreamBuffer()->WriteBack(c
);
643 } else if (c
== '+') {
660 wxInputStream
& wxInputStream::operator>>(unsigned short& i
)
665 i
= (unsigned short)l
;
669 wxInputStream
& wxInputStream::operator>>(unsigned int& i
)
678 wxInputStream
& wxInputStream::operator>>(unsigned long& i
)
680 /* I only implemented a simple integer parser */
683 while (isspace( c
= GetC() ) )
688 InputStreamBuffer()->WriteBack(c
);
700 wxInputStream
& wxInputStream::operator>>(double& f
)
702 /* I only implemented a simple float parser */
705 while (isspace( c
= GetC() ) )
709 if (! (c
== '-' || isdigit(c
)) ) {
710 InputStreamBuffer()->WriteBack(c
);
717 } else if (c
== '+') {
725 f
= f
*10 + (c
- '0');
730 double f_multiplicator
= (double) 0.1;
734 f
+= (c
-'0')*f_multiplicator
;
735 f_multiplicator
/= 10;
746 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
748 wxObjectInputStream
obj_s(*this);
749 obj
= obj_s
.LoadObject();
755 // ----------------------------------------------------------------------------
757 // ----------------------------------------------------------------------------
758 wxOutputStream::wxOutputStream()
761 m_o_destroybuf
= TRUE
;
762 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
765 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
768 m_o_destroybuf
= FALSE
;
769 m_o_streambuf
= buffer
;
772 wxOutputStream::~wxOutputStream()
775 delete m_o_streambuf
;
778 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
780 m_o_streambuf
->Write(buffer
, size
);
784 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
786 stream_in
.Read(*this);
790 off_t
wxOutputStream::TellO() const
792 return m_o_streambuf
->Tell();
795 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
797 return m_o_streambuf
->Seek(pos
, mode
);
800 void wxOutputStream::Sync()
802 m_o_streambuf
->FlushBuffer();
805 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
807 return Write(string
, strlen(string
));
810 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
813 const wxWX2MBbuf buf
= string
.mb_str();
816 return Write(string
, string
.Len());
820 wxOutputStream
& wxOutputStream::operator<<(char c
)
825 wxOutputStream
& wxOutputStream::operator<<(signed short i
)
827 signed long l
= (signed long)i
;
831 wxOutputStream
& wxOutputStream::operator<<(signed int i
)
833 signed long l
= (signed long)i
;
837 wxOutputStream
& wxOutputStream::operator<<(signed long i
)
840 strlong
.Printf(_T("%ld"), i
);
841 return *this << strlong
;
844 wxOutputStream
& wxOutputStream::operator<<(unsigned short i
)
846 unsigned long l
= (unsigned long)i
;
850 wxOutputStream
& wxOutputStream::operator<<(unsigned int i
)
852 unsigned long l
= (unsigned long)i
;
856 wxOutputStream
& wxOutputStream::operator<<(unsigned long i
)
859 strlong
.Printf(_T("%lu"), i
);
860 return *this << strlong
;
863 wxOutputStream
& wxOutputStream::operator<<(double f
)
867 strfloat
.Printf(_T("%f"), f
);
868 return *this << strfloat
;
872 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
874 wxObjectOutputStream
obj_s(*this);
875 obj_s
.SaveObject(obj
);
880 // ----------------------------------------------------------------------------
881 // wxFilterInputStream
882 // ----------------------------------------------------------------------------
883 wxFilterInputStream::wxFilterInputStream()
884 : wxInputStream(NULL
)
886 // WARNING streambuf set to NULL !
889 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
890 : wxInputStream(stream
.InputStreamBuffer())
892 m_parent_i_stream
= &stream
;
895 wxFilterInputStream::~wxFilterInputStream()
899 // ----------------------------------------------------------------------------
900 // wxFilterOutputStream
901 // ----------------------------------------------------------------------------
902 wxFilterOutputStream::wxFilterOutputStream()
903 : wxOutputStream(NULL
)
907 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
908 : wxOutputStream(stream
.OutputStreamBuffer())
910 m_parent_o_stream
= &stream
;
913 wxFilterOutputStream::~wxFilterOutputStream()
917 // ----------------------------------------------------------------------------
918 // Some IOManip function
919 // ----------------------------------------------------------------------------
921 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
924 return stream
.Write("\r\n", 2);
926 return stream
.Write("\n", 1);