]>
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 #define CHECK_ERROR(err) \
34 if (m_stream->m_lasterror == wxStream_NOERROR) \
35 m_stream->m_lasterror = err
37 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
)
38 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
39 m_buffer_size(0), m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
),
40 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
)
44 wxStreamBuffer::wxStreamBuffer(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(FALSE
), m_stream(NULL
),
47 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
)
49 m_stream
= new wxStreamBase();
52 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
54 m_buffer_start
= buffer
.m_buffer_start
;
55 m_buffer_end
= buffer
.m_buffer_end
;
56 m_buffer_pos
= buffer
.m_buffer_pos
;
57 m_buffer_size
= buffer
.m_buffer_size
;
58 m_fixed
= buffer
.m_fixed
;
59 m_flushable
= buffer
.m_flushable
;
60 m_stream
= buffer
.m_stream
;
61 m_mode
= buffer
.m_mode
;
63 m_destroystream
= FALSE
;
66 wxStreamBuffer::~wxStreamBuffer()
69 wxDELETEA(m_buffer_start
);
74 size_t wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
)
78 ptrback
= AllocSpaceWBack(bufsize
);
82 memcpy(ptrback
, buf
, bufsize
);
86 bool wxStreamBuffer::WriteBack(char c
)
90 ptrback
= AllocSpaceWBack(1);
98 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
101 wxDELETEA(m_buffer_start
);
102 m_buffer_start
= buffer_start
;
103 m_buffer_end
= buffer_end
;
105 m_buffer_size
= m_buffer_end
-m_buffer_start
;
106 m_destroybuf
= FALSE
;
110 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
115 wxDELETEA(m_buffer_start
);
118 m_buffer_start
= NULL
;
125 b_start
= new char[bufsize
];
126 SetBufferIO(b_start
, b_start
+ bufsize
);
130 void wxStreamBuffer::ResetBuffer()
133 m_buffer_pos
= m_buffer_end
;
135 m_buffer_pos
= m_buffer_start
;
138 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
)
142 m_wbacksize
+= needed_size
;
145 temp_b
= (char *)malloc(m_wbacksize
);
147 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
151 return (char *)((size_t)m_wback
+(m_wbacksize
-needed_size
));
154 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
)
156 size_t s_toget
= m_wbacksize
-m_wbackcur
;
161 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
163 m_wbackcur
+= s_toget
;
164 if (m_wbackcur
== m_wbacksize
) {
166 m_wback
= (char *)NULL
;
174 bool wxStreamBuffer::FillBuffer()
178 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
179 m_buffer_end
= m_buffer_start
+count
;
180 m_buffer_pos
= m_buffer_start
;
187 bool wxStreamBuffer::FlushBuffer()
189 size_t count
, current
;
191 if (m_buffer_pos
== m_buffer_start
|| !m_flushable
)
194 current
= m_buffer_pos
-m_buffer_start
;
195 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
196 if (count
!= current
)
198 m_buffer_pos
= m_buffer_start
;
203 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
205 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
210 memcpy(buffer
, m_buffer_pos
, s_toget
);
211 m_buffer_pos
+= s_toget
;
214 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
216 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
218 if (s_toput
< size
&& !m_fixed
) {
219 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
221 m_buffer_size
+= size
;
222 m_buffer_end
= m_buffer_start
+m_buffer_size
;
227 memcpy(m_buffer_pos
, buffer
, s_toput
);
228 m_buffer_pos
+= s_toput
;
231 void wxStreamBuffer::PutChar(char c
)
233 wxASSERT(m_stream
!= NULL
);
235 if (!m_buffer_size
) {
236 m_stream
->OnSysWrite(&c
, 1);
240 if (!GetDataLeft() && !FlushBuffer()) {
241 CHECK_ERROR(wxStream_READ_ERR
);
246 m_stream
->m_lastcount
= 1;
249 char wxStreamBuffer::GetChar()
253 wxASSERT(m_stream
!= NULL
);
255 if (!m_buffer_size
) {
256 m_stream
->OnSysRead(&c
, 1);
260 if (!GetDataLeft()) {
261 CHECK_ERROR(wxStream_READ_ERR
);
265 GetFromBuffer(&c
, 1);
266 m_stream
->m_lastcount
= 1;
270 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
272 wxASSERT(m_stream
!= NULL
);
274 // ------------------
275 // Buffering disabled
276 // ------------------
278 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
279 size
-= m_stream
->m_lastcount
;
281 return m_stream
->m_lastcount
;
283 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
286 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
291 size_t buf_left
, orig_size
= size
;
294 buf_left
= GetDataLeft();
296 // First case: the requested buffer is larger than the stream buffer,
298 if (size
> buf_left
) {
299 GetFromBuffer(buffer
, buf_left
);
301 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
304 CHECK_ERROR(wxStream_READ_ERR
);
305 return (m_stream
->m_lastcount
= orig_size
-size
);
309 // Second case: we just copy from the stream buffer.
310 GetFromBuffer(buffer
, size
);
314 return (m_stream
->m_lastcount
+= orig_size
);
317 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
319 char buf
[BUF_TEMP_SIZE
];
320 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
322 while (bytes_read
== BUF_TEMP_SIZE
) {
323 bytes_read
= Read(buf
, bytes_read
);
324 bytes_read
= s_buf
->Write(buf
, bytes_read
);
330 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
332 wxASSERT(m_stream
!= NULL
);
334 // ------------------
335 // Buffering disabled
336 // ------------------
339 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
341 // ------------------
343 // ------------------
345 size_t buf_left
, orig_size
= size
;
348 buf_left
= m_buffer_end
- m_buffer_pos
;
350 // First case: the buffer to write is larger than the stream buffer,
352 if (size
> buf_left
) {
353 PutToBuffer(buffer
, buf_left
);
355 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
357 if (!FlushBuffer()) {
358 CHECK_ERROR(wxStream_WRITE_ERR
);
359 return (m_stream
->m_lastcount
= orig_size
-size
);
362 m_buffer_pos
= m_buffer_start
;
366 // Second case: just copy it in the stream buffer.
367 PutToBuffer(buffer
, size
);
371 return (m_stream
->m_lastcount
= orig_size
);
374 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
376 char buf
[BUF_TEMP_SIZE
];
377 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
;
380 while (bytes_count
== BUF_TEMP_SIZE
) {
381 s_size
= (sbuf
->GetDataLeft() < GetDataLeft()) ? sbuf
->GetDataLeft() : GetDataLeft();
382 if (s_size
< bytes_count
)
383 bytes_count
= s_size
;
384 bytes_count
= sbuf
->Read(buf
, bytes_count
);
385 bytes_count
= Write(buf
, bytes_count
);
391 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
393 off_t ret_off
, diff
, last_access
;
395 last_access
= GetLastAccess();
398 diff
= pos
+ GetIntPosition();
399 if (diff
< 0 || diff
> last_access
)
400 return wxInvalidOffset
;
401 SetIntPosition(diff
);
407 // We'll try to compute an internal position later ...
408 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
412 case wxFromCurrent
: {
413 diff
= pos
+ GetIntPosition();
415 if ( (diff
> last_access
) || (diff
< 0) ) {
416 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
420 SetIntPosition(diff
);
425 // Hard to compute: always seek to the requested position.
426 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
430 return wxInvalidOffset
;
433 off_t
wxStreamBuffer::Tell() const
438 pos
= m_stream
->OnSysTell();
439 if (pos
== wxInvalidOffset
)
440 return wxInvalidOffset
;
441 return pos
- GetLastAccess() + GetIntPosition();
443 return GetIntPosition();
446 size_t wxStreamBuffer::GetDataLeft()
448 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
450 return m_buffer_end
-m_buffer_pos
;
453 // ----------------------------------------------------------------------------
455 // ----------------------------------------------------------------------------
457 wxStreamBase::wxStreamBase()
459 m_lasterror
= wxStream_NOERROR
;
463 wxStreamBase::~wxStreamBase()
467 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
472 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
477 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
479 return wxInvalidOffset
;
482 off_t
wxStreamBase::OnSysTell() const
484 return wxInvalidOffset
;
487 // ----------------------------------------------------------------------------
489 // ----------------------------------------------------------------------------
491 wxInputStream::wxInputStream()
494 m_i_destroybuf
= TRUE
;
495 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
498 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
501 m_i_destroybuf
= FALSE
;
502 m_i_streambuf
= buffer
;
505 wxInputStream::~wxInputStream()
508 delete m_i_streambuf
;
511 char wxInputStream::GetC()
514 m_i_streambuf
->Read(&c
, 1);
518 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
520 m_i_streambuf
->Read(buffer
, size
);
521 // wxStreamBuffer sets all variables for us
525 char wxInputStream::Peek()
527 m_i_streambuf
->GetDataLeft();
529 return *(m_i_streambuf
->GetBufferPos());
533 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
535 char buf
[BUF_TEMP_SIZE
];
536 size_t bytes_read
= BUF_TEMP_SIZE
;
538 while (bytes_read
== BUF_TEMP_SIZE
) {
539 bytes_read
= Read(buf
, bytes_read
).LastRead();
540 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
545 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
547 return m_i_streambuf
->Seek(pos
, mode
);
550 off_t
wxInputStream::TellI() const
552 return m_i_streambuf
->Tell();
555 // --------------------
556 // Overloaded operators
557 // --------------------
559 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
561 wxDataInputStream
s(*this);
567 wxInputStream
& wxInputStream::operator>>(char& c
)
573 wxInputStream
& wxInputStream::operator>>(short& i
)
582 wxInputStream
& wxInputStream::operator>>(int& i
)
591 wxInputStream
& wxInputStream::operator>>(long& i
)
593 /* I only implemented a simple integer parser */
596 while (isspace( c
= GetC() ) )
600 if (! (c
== '-' || isdigit(c
)) ) {
601 InputStreamBuffer()->WriteBack(c
);
621 wxInputStream
& wxInputStream::operator>>(double& f
)
623 /* I only implemented a simple float parser */
626 while (isspace( c
= GetC() ) )
630 if (! (c
== '-' || isdigit(c
)) ) {
631 InputStreamBuffer()->WriteBack(c
);
642 f
= f
*10 + (c
- '0');
647 double f_multiplicator
= (double) 0.1;
651 f
+= (c
-'0')*f_multiplicator
;
652 f_multiplicator
/= 10;
663 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
665 wxObjectInputStream
obj_s(*this);
666 obj
= obj_s
.LoadObject();
672 // ----------------------------------------------------------------------------
674 // ----------------------------------------------------------------------------
675 wxOutputStream::wxOutputStream()
678 m_o_destroybuf
= TRUE
;
679 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
682 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
685 m_o_destroybuf
= FALSE
;
686 m_o_streambuf
= buffer
;
689 wxOutputStream::~wxOutputStream()
692 delete m_o_streambuf
;
695 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
697 m_o_streambuf
->Write(buffer
, size
);
701 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
703 stream_in
.Read(*this);
707 off_t
wxOutputStream::TellO() const
709 return m_o_streambuf
->Tell();
712 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
714 return m_o_streambuf
->Seek(pos
, mode
);
717 void wxOutputStream::Sync()
719 m_o_streambuf
->FlushBuffer();
722 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
724 return Write(string
, strlen(string
));
727 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
729 return Write(string
, string
.Len());
732 wxOutputStream
& wxOutputStream::operator<<(char c
)
737 wxOutputStream
& wxOutputStream::operator<<(short i
)
741 strint
.Printf("%i", i
);
742 return Write(strint
, strint
.Len());
745 wxOutputStream
& wxOutputStream::operator<<(int i
)
749 strint
.Printf("%i", i
);
750 return Write(strint
, strint
.Len());
753 wxOutputStream
& wxOutputStream::operator<<(long i
)
757 strlong
.Printf("%i", i
);
758 return Write((const char *)strlong
, strlong
.Len());
761 wxOutputStream
& wxOutputStream::operator<<(double f
)
765 strfloat
.Printf("%f", f
);
766 return Write(strfloat
, strfloat
.Len());
770 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
772 wxObjectOutputStream
obj_s(*this);
773 obj_s
.SaveObject(obj
);
778 // ----------------------------------------------------------------------------
779 // wxFilterInputStream
780 // ----------------------------------------------------------------------------
781 wxFilterInputStream::wxFilterInputStream()
782 : wxInputStream(NULL
)
784 // WARNING streambuf set to NULL !
787 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
788 : wxInputStream(stream
.InputStreamBuffer())
790 m_parent_i_stream
= &stream
;
793 wxFilterInputStream::~wxFilterInputStream()
797 // ----------------------------------------------------------------------------
798 // wxFilterOutputStream
799 // ----------------------------------------------------------------------------
800 wxFilterOutputStream::wxFilterOutputStream()
801 : wxOutputStream(NULL
)
805 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
806 : wxOutputStream(stream
.OutputStreamBuffer())
808 m_parent_o_stream
= &stream
;
811 wxFilterOutputStream::~wxFilterOutputStream()
815 // ----------------------------------------------------------------------------
816 // Some IOManip function
817 // ----------------------------------------------------------------------------
819 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
822 return stream
.Write("\r\n", 2);
824 return stream
.Write("\n", 1);