]>
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);
287 m_stream
->m_lastcount
= 1;
291 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
293 wxASSERT(m_stream
!= NULL
);
298 // ------------------
299 // Buffering disabled
300 // ------------------
302 m_stream
->m_lasterror
= wxStream_NOERROR
;
303 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
304 size
-= m_stream
->m_lastcount
;
306 return m_stream
->m_lastcount
;
308 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
311 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
316 size_t buf_left
, orig_size
= size
;
319 buf_left
= GetDataLeft();
321 // First case: the requested buffer is larger than the stream buffer,
323 if (size
> buf_left
) {
324 GetFromBuffer(buffer
, buf_left
);
326 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
329 CHECK_ERROR(wxStream_READ_ERR
);
330 return (m_stream
->m_lastcount
= orig_size
-size
);
334 // Second case: we just copy from the stream buffer.
335 GetFromBuffer(buffer
, size
);
339 return (m_stream
->m_lastcount
+= orig_size
);
342 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
344 char buf
[BUF_TEMP_SIZE
];
345 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
350 while (bytes_read
!= 0) {
351 bytes_read
= Read(buf
, bytes_read
);
352 bytes_read
= s_buf
->Write(buf
, bytes_read
);
358 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
360 wxASSERT(m_stream
!= NULL
);
365 // ------------------
366 // Buffering disabled
367 // ------------------
369 m_stream
->m_lasterror
= wxStream_NOERROR
;
371 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
373 // ------------------
375 // ------------------
377 size_t buf_left
, orig_size
= size
;
380 buf_left
= m_buffer_end
- m_buffer_pos
;
382 // First case: the buffer to write is larger than the stream buffer,
384 if (size
> buf_left
) {
385 PutToBuffer(buffer
, buf_left
);
387 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
389 if (!FlushBuffer()) {
390 CHECK_ERROR(wxStream_WRITE_ERR
);
391 return (m_stream
->m_lastcount
= orig_size
-size
);
394 m_buffer_pos
= m_buffer_start
;
398 // Second case: just copy it in the stream buffer.
399 PutToBuffer(buffer
, size
);
403 return (m_stream
->m_lastcount
= orig_size
);
406 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
408 char buf
[BUF_TEMP_SIZE
];
409 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
, b_count2
;
414 while (bytes_count
== BUF_TEMP_SIZE
) {
415 b_count2
= sbuf
->Read(buf
, bytes_count
);
416 bytes_count
= Write(buf
, b_count2
);
417 if (b_count2
> bytes_count
)
418 sbuf
->WriteBack(buf
+bytes_count
, b_count2
-bytes_count
);
424 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
426 off_t ret_off
, diff
, last_access
;
428 last_access
= GetLastAccess();
431 diff
= pos
+ GetIntPosition();
432 if (diff
< 0 || diff
> last_access
)
433 return wxInvalidOffset
;
434 SetIntPosition(diff
);
440 // We'll try to compute an internal position later ...
441 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
445 case wxFromCurrent
: {
446 diff
= pos
+ GetIntPosition();
448 if ( (diff
> last_access
) || (diff
< 0) ) {
449 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
453 SetIntPosition(diff
);
458 // Hard to compute: always seek to the requested position.
459 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
463 return wxInvalidOffset
;
466 off_t
wxStreamBuffer::Tell() const
471 pos
= m_stream
->OnSysTell();
472 if (pos
== wxInvalidOffset
)
473 return wxInvalidOffset
;
474 return pos
- GetLastAccess() + GetIntPosition();
476 return GetIntPosition();
479 size_t wxStreamBuffer::GetDataLeft()
481 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
483 return m_buffer_end
-m_buffer_pos
;
486 // ----------------------------------------------------------------------------
488 // ----------------------------------------------------------------------------
490 wxStreamBase::wxStreamBase()
492 m_lasterror
= wxStream_NOERROR
;
496 wxStreamBase::~wxStreamBase()
500 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
505 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
510 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
512 return wxInvalidOffset
;
515 off_t
wxStreamBase::OnSysTell() const
517 return wxInvalidOffset
;
520 // ----------------------------------------------------------------------------
522 // ----------------------------------------------------------------------------
524 wxInputStream::wxInputStream()
527 m_i_destroybuf
= TRUE
;
528 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
531 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
534 m_i_destroybuf
= FALSE
;
535 m_i_streambuf
= buffer
;
538 wxInputStream::~wxInputStream()
541 delete m_i_streambuf
;
544 char wxInputStream::GetC()
547 m_i_streambuf
->Read(&c
, 1);
551 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
553 m_i_streambuf
->Read(buffer
, size
);
554 // wxStreamBuffer sets all variables for us
558 char wxInputStream::Peek()
560 m_i_streambuf
->GetDataLeft();
562 return *(m_i_streambuf
->GetBufferPos());
566 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
568 char buf
[BUF_TEMP_SIZE
];
569 size_t bytes_read
= BUF_TEMP_SIZE
;
571 while (bytes_read
== BUF_TEMP_SIZE
) {
572 bytes_read
= Read(buf
, bytes_read
).LastRead();
573 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
578 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
580 return m_i_streambuf
->Seek(pos
, mode
);
583 off_t
wxInputStream::TellI() const
585 return m_i_streambuf
->Tell();
588 // --------------------
589 // Overloaded operators
590 // --------------------
592 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
594 wxDataInputStream
s(*this);
600 wxInputStream
& wxInputStream::operator>>(char& c
)
606 wxInputStream
& wxInputStream::operator>>(short& i
)
615 wxInputStream
& wxInputStream::operator>>(int& i
)
624 wxInputStream
& wxInputStream::operator>>(long& i
)
626 /* I only implemented a simple integer parser */
629 while (isspace( c
= GetC() ) )
633 if (! (c
== '-' || isdigit(c
)) ) {
634 InputStreamBuffer()->WriteBack(c
);
654 wxInputStream
& wxInputStream::operator>>(double& f
)
656 /* I only implemented a simple float parser */
659 while (isspace( c
= GetC() ) )
663 if (! (c
== '-' || isdigit(c
)) ) {
664 InputStreamBuffer()->WriteBack(c
);
675 f
= f
*10 + (c
- '0');
680 double f_multiplicator
= (double) 0.1;
684 f
+= (c
-'0')*f_multiplicator
;
685 f_multiplicator
/= 10;
696 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
698 wxObjectInputStream
obj_s(*this);
699 obj
= obj_s
.LoadObject();
705 // ----------------------------------------------------------------------------
707 // ----------------------------------------------------------------------------
708 wxOutputStream::wxOutputStream()
711 m_o_destroybuf
= TRUE
;
712 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
715 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
718 m_o_destroybuf
= FALSE
;
719 m_o_streambuf
= buffer
;
722 wxOutputStream::~wxOutputStream()
725 delete m_o_streambuf
;
728 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
730 m_o_streambuf
->Write(buffer
, size
);
734 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
736 stream_in
.Read(*this);
740 off_t
wxOutputStream::TellO() const
742 return m_o_streambuf
->Tell();
745 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
747 return m_o_streambuf
->Seek(pos
, mode
);
750 void wxOutputStream::Sync()
752 m_o_streambuf
->FlushBuffer();
755 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
757 return Write(string
, strlen(string
));
760 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
763 const wxWX2MBbuf buf
= string
.mb_str();
766 return Write(string
, string
.Len());
770 wxOutputStream
& wxOutputStream::operator<<(char c
)
775 wxOutputStream
& wxOutputStream::operator<<(short i
)
779 strint
.Printf(_T("%i"), i
);
780 return *this << strint
;
783 wxOutputStream
& wxOutputStream::operator<<(int i
)
787 strint
.Printf(_T("%i"), i
);
788 return *this << strint
;
791 wxOutputStream
& wxOutputStream::operator<<(long i
)
795 strlong
.Printf(_T("%i"), i
);
796 return *this << strlong
;
799 wxOutputStream
& wxOutputStream::operator<<(double f
)
803 strfloat
.Printf(_T("%f"), f
);
804 return *this << strfloat
;
808 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
810 wxObjectOutputStream
obj_s(*this);
811 obj_s
.SaveObject(obj
);
816 // ----------------------------------------------------------------------------
817 // wxFilterInputStream
818 // ----------------------------------------------------------------------------
819 wxFilterInputStream::wxFilterInputStream()
820 : wxInputStream(NULL
)
822 // WARNING streambuf set to NULL !
825 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
826 : wxInputStream(stream
.InputStreamBuffer())
828 m_parent_i_stream
= &stream
;
831 wxFilterInputStream::~wxFilterInputStream()
835 // ----------------------------------------------------------------------------
836 // wxFilterOutputStream
837 // ----------------------------------------------------------------------------
838 wxFilterOutputStream::wxFilterOutputStream()
839 : wxOutputStream(NULL
)
843 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
844 : wxOutputStream(stream
.OutputStreamBuffer())
846 m_parent_o_stream
= &stream
;
849 wxFilterOutputStream::~wxFilterOutputStream()
853 // ----------------------------------------------------------------------------
854 // Some IOManip function
855 // ----------------------------------------------------------------------------
857 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
860 return stream
.Write("\r\n", 2);
862 return stream
.Write("\n", 1);