]>
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_wback(NULL
), m_wbacksize(0), m_wbackcur(0),
40 m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
),
41 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
)
45 wxStreamBuffer::wxStreamBuffer(BufMode mode
)
46 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
47 m_buffer_size(0), m_wback(NULL
), m_wbacksize(0), m_wbackcur(0),
48 m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
),
49 m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
)
51 m_stream
= new wxStreamBase();
54 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
)
56 m_buffer_start
= buffer
.m_buffer_start
;
57 m_buffer_end
= buffer
.m_buffer_end
;
58 m_buffer_pos
= buffer
.m_buffer_pos
;
59 m_buffer_size
= buffer
.m_buffer_size
;
60 m_fixed
= buffer
.m_fixed
;
61 m_flushable
= buffer
.m_flushable
;
62 m_stream
= buffer
.m_stream
;
63 m_mode
= buffer
.m_mode
;
65 m_destroystream
= FALSE
;
71 wxStreamBuffer::~wxStreamBuffer()
76 wxDELETEA(m_buffer_start
);
81 size_t wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
)
85 ptrback
= AllocSpaceWBack(bufsize
);
89 memcpy(ptrback
, buf
, bufsize
);
93 bool wxStreamBuffer::WriteBack(char c
)
97 ptrback
= AllocSpaceWBack(1);
105 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
108 wxDELETEA(m_buffer_start
);
109 m_buffer_start
= buffer_start
;
110 m_buffer_end
= buffer_end
;
112 m_buffer_size
= m_buffer_end
-m_buffer_start
;
113 m_destroybuf
= FALSE
;
117 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
122 wxDELETEA(m_buffer_start
);
125 m_buffer_start
= NULL
;
132 b_start
= new char[bufsize
];
133 SetBufferIO(b_start
, b_start
+ bufsize
);
137 void wxStreamBuffer::ResetBuffer()
139 m_stream
->m_lasterror
= wxStream_NOERROR
;
141 m_buffer_pos
= m_buffer_end
;
143 m_buffer_pos
= m_buffer_start
;
146 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
)
150 m_wbacksize
+= needed_size
;
153 temp_b
= (char *)malloc(m_wbacksize
);
155 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
160 printf("Buffer(0x%x)->Write: 0x%x, %d\n", this, m_wback
, m_wbacksize
);
161 return (char *)(m_wback
+(m_wbacksize
-needed_size
));
164 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
)
166 size_t s_toget
= m_wbacksize
-m_wbackcur
;
168 printf("Buffer(0x%x): 0x%x, %d\n", this, m_wback
, m_wbacksize
);
172 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
174 m_wbackcur
+= s_toget
;
175 if (m_wbackcur
== m_wbacksize
) {
177 m_wback
= (char *)NULL
;
185 bool wxStreamBuffer::FillBuffer()
189 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
190 m_buffer_end
= m_buffer_start
+count
;
191 m_buffer_pos
= m_buffer_start
;
198 bool wxStreamBuffer::FlushBuffer()
200 size_t count
, current
;
202 if (m_buffer_pos
== m_buffer_start
|| !m_flushable
)
205 current
= m_buffer_pos
-m_buffer_start
;
206 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
207 if (count
!= current
)
209 m_buffer_pos
= m_buffer_start
;
214 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
216 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
221 memcpy(buffer
, m_buffer_pos
, s_toget
);
222 m_buffer_pos
+= s_toget
;
225 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
227 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
229 if (s_toput
< size
&& !m_fixed
) {
230 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
232 m_buffer_size
+= size
;
233 m_buffer_end
= m_buffer_start
+m_buffer_size
;
238 memcpy(m_buffer_pos
, buffer
, s_toput
);
239 m_buffer_pos
+= s_toput
;
242 void wxStreamBuffer::PutChar(char c
)
244 wxASSERT(m_stream
!= NULL
);
246 if (!m_buffer_size
) {
247 m_stream
->OnSysWrite(&c
, 1);
251 if (!GetDataLeft() && !FlushBuffer()) {
252 CHECK_ERROR(wxStream_READ_ERR
);
257 m_stream
->m_lastcount
= 1;
260 char wxStreamBuffer::GetChar()
264 wxASSERT(m_stream
!= NULL
);
266 if (!m_buffer_size
) {
267 m_stream
->OnSysRead(&c
, 1);
271 if (!GetDataLeft()) {
272 CHECK_ERROR(wxStream_READ_ERR
);
276 GetFromBuffer(&c
, 1);
277 m_stream
->m_lastcount
= 1;
281 size_t wxStreamBuffer::Read(void *buffer
, size_t size
)
283 wxASSERT(m_stream
!= NULL
);
285 // ------------------
286 // Buffering disabled
287 // ------------------
289 m_stream
->m_lasterror
= wxStream_NOERROR
;
290 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
291 size
-= m_stream
->m_lastcount
;
293 return m_stream
->m_lastcount
;
295 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
298 return (m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
));
303 size_t buf_left
, orig_size
= size
;
306 buf_left
= GetDataLeft();
308 // First case: the requested buffer is larger than the stream buffer,
310 if (size
> buf_left
) {
311 GetFromBuffer(buffer
, buf_left
);
313 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
316 CHECK_ERROR(wxStream_READ_ERR
);
317 return (m_stream
->m_lastcount
= orig_size
-size
);
321 // Second case: we just copy from the stream buffer.
322 GetFromBuffer(buffer
, size
);
326 return (m_stream
->m_lastcount
+= orig_size
);
329 size_t wxStreamBuffer::Read(wxStreamBuffer
*s_buf
)
331 char buf
[BUF_TEMP_SIZE
];
332 size_t s
= 0, bytes_read
= BUF_TEMP_SIZE
;
334 while (bytes_read
== BUF_TEMP_SIZE
) {
335 bytes_read
= Read(buf
, bytes_read
);
336 bytes_read
= s_buf
->Write(buf
, bytes_read
);
342 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
)
344 wxASSERT(m_stream
!= NULL
);
346 // ------------------
347 // Buffering disabled
348 // ------------------
350 m_stream
->m_lasterror
= wxStream_NOERROR
;
352 return (m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
));
354 // ------------------
356 // ------------------
358 size_t buf_left
, orig_size
= size
;
361 buf_left
= m_buffer_end
- m_buffer_pos
;
363 // First case: the buffer to write is larger than the stream buffer,
365 if (size
> buf_left
) {
366 PutToBuffer(buffer
, buf_left
);
368 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
370 if (!FlushBuffer()) {
371 CHECK_ERROR(wxStream_WRITE_ERR
);
372 return (m_stream
->m_lastcount
= orig_size
-size
);
375 m_buffer_pos
= m_buffer_start
;
379 // Second case: just copy it in the stream buffer.
380 PutToBuffer(buffer
, size
);
384 return (m_stream
->m_lastcount
= orig_size
);
387 size_t wxStreamBuffer::Write(wxStreamBuffer
*sbuf
)
389 char buf
[BUF_TEMP_SIZE
];
390 size_t s
= 0, bytes_count
= BUF_TEMP_SIZE
, b_count2
;
392 while (bytes_count
== BUF_TEMP_SIZE
) {
393 b_count2
= sbuf
->Read(buf
, bytes_count
);
394 bytes_count
= Write(buf
, b_count2
);
395 if (b_count2
> bytes_count
)
396 sbuf
->WriteBack(buf
+bytes_count
, b_count2
-bytes_count
);
402 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
404 off_t ret_off
, diff
, last_access
;
406 last_access
= GetLastAccess();
409 diff
= pos
+ GetIntPosition();
410 if (diff
< 0 || diff
> last_access
)
411 return wxInvalidOffset
;
412 SetIntPosition(diff
);
418 // We'll try to compute an internal position later ...
419 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
423 case wxFromCurrent
: {
424 diff
= pos
+ GetIntPosition();
426 if ( (diff
> last_access
) || (diff
< 0) ) {
427 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
431 SetIntPosition(diff
);
436 // Hard to compute: always seek to the requested position.
437 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
441 return wxInvalidOffset
;
444 off_t
wxStreamBuffer::Tell() const
449 pos
= m_stream
->OnSysTell();
450 if (pos
== wxInvalidOffset
)
451 return wxInvalidOffset
;
452 return pos
- GetLastAccess() + GetIntPosition();
454 return GetIntPosition();
457 size_t wxStreamBuffer::GetDataLeft()
459 if (m_buffer_end
== m_buffer_pos
&& m_flushable
)
461 return m_buffer_end
-m_buffer_pos
;
464 // ----------------------------------------------------------------------------
466 // ----------------------------------------------------------------------------
468 wxStreamBase::wxStreamBase()
470 m_lasterror
= wxStream_NOERROR
;
474 wxStreamBase::~wxStreamBase()
478 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
))
483 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
))
488 off_t
wxStreamBase::OnSysSeek(off_t
WXUNUSED(seek
), wxSeekMode
WXUNUSED(mode
))
490 return wxInvalidOffset
;
493 off_t
wxStreamBase::OnSysTell() const
495 return wxInvalidOffset
;
498 // ----------------------------------------------------------------------------
500 // ----------------------------------------------------------------------------
502 wxInputStream::wxInputStream()
505 m_i_destroybuf
= TRUE
;
506 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
509 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
512 m_i_destroybuf
= FALSE
;
513 m_i_streambuf
= buffer
;
516 wxInputStream::~wxInputStream()
519 delete m_i_streambuf
;
522 char wxInputStream::GetC()
525 m_i_streambuf
->Read(&c
, 1);
529 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
531 m_i_streambuf
->Read(buffer
, size
);
532 // wxStreamBuffer sets all variables for us
536 char wxInputStream::Peek()
538 m_i_streambuf
->GetDataLeft();
540 return *(m_i_streambuf
->GetBufferPos());
544 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
546 char buf
[BUF_TEMP_SIZE
];
547 size_t bytes_read
= BUF_TEMP_SIZE
;
549 while (bytes_read
== BUF_TEMP_SIZE
) {
550 bytes_read
= Read(buf
, bytes_read
).LastRead();
551 bytes_read
= stream_out
.Write(buf
, bytes_read
).LastWrite();
556 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
558 return m_i_streambuf
->Seek(pos
, mode
);
561 off_t
wxInputStream::TellI() const
563 return m_i_streambuf
->Tell();
566 // --------------------
567 // Overloaded operators
568 // --------------------
570 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
572 wxDataInputStream
s(*this);
578 wxInputStream
& wxInputStream::operator>>(char& c
)
584 wxInputStream
& wxInputStream::operator>>(short& i
)
593 wxInputStream
& wxInputStream::operator>>(int& i
)
602 wxInputStream
& wxInputStream::operator>>(long& i
)
604 /* I only implemented a simple integer parser */
607 while (isspace( c
= GetC() ) )
611 if (! (c
== '-' || isdigit(c
)) ) {
612 InputStreamBuffer()->WriteBack(c
);
632 wxInputStream
& wxInputStream::operator>>(double& f
)
634 /* I only implemented a simple float parser */
637 while (isspace( c
= GetC() ) )
641 if (! (c
== '-' || isdigit(c
)) ) {
642 InputStreamBuffer()->WriteBack(c
);
653 f
= f
*10 + (c
- '0');
658 double f_multiplicator
= (double) 0.1;
662 f
+= (c
-'0')*f_multiplicator
;
663 f_multiplicator
/= 10;
674 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
676 wxObjectInputStream
obj_s(*this);
677 obj
= obj_s
.LoadObject();
683 // ----------------------------------------------------------------------------
685 // ----------------------------------------------------------------------------
686 wxOutputStream::wxOutputStream()
689 m_o_destroybuf
= TRUE
;
690 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
693 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
696 m_o_destroybuf
= FALSE
;
697 m_o_streambuf
= buffer
;
700 wxOutputStream::~wxOutputStream()
703 delete m_o_streambuf
;
706 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
708 m_o_streambuf
->Write(buffer
, size
);
712 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
714 stream_in
.Read(*this);
718 off_t
wxOutputStream::TellO() const
720 return m_o_streambuf
->Tell();
723 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
725 return m_o_streambuf
->Seek(pos
, mode
);
728 void wxOutputStream::Sync()
730 m_o_streambuf
->FlushBuffer();
733 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
735 return Write(string
, strlen(string
));
738 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
740 return Write(string
, string
.Len());
743 wxOutputStream
& wxOutputStream::operator<<(char c
)
748 wxOutputStream
& wxOutputStream::operator<<(short i
)
752 strint
.Printf("%i", i
);
753 return Write(strint
, strint
.Len());
756 wxOutputStream
& wxOutputStream::operator<<(int i
)
760 strint
.Printf("%i", i
);
761 return Write(strint
, strint
.Len());
764 wxOutputStream
& wxOutputStream::operator<<(long i
)
768 strlong
.Printf("%i", i
);
769 return Write((const char *)strlong
, strlong
.Len());
772 wxOutputStream
& wxOutputStream::operator<<(double f
)
776 strfloat
.Printf("%f", f
);
777 return Write(strfloat
, strfloat
.Len());
781 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
783 wxObjectOutputStream
obj_s(*this);
784 obj_s
.SaveObject(obj
);
789 // ----------------------------------------------------------------------------
790 // wxFilterInputStream
791 // ----------------------------------------------------------------------------
792 wxFilterInputStream::wxFilterInputStream()
793 : wxInputStream(NULL
)
795 // WARNING streambuf set to NULL !
798 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
799 : wxInputStream(stream
.InputStreamBuffer())
801 m_parent_i_stream
= &stream
;
804 wxFilterInputStream::~wxFilterInputStream()
808 // ----------------------------------------------------------------------------
809 // wxFilterOutputStream
810 // ----------------------------------------------------------------------------
811 wxFilterOutputStream::wxFilterOutputStream()
812 : wxOutputStream(NULL
)
816 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
817 : wxOutputStream(stream
.OutputStreamBuffer())
819 m_parent_o_stream
= &stream
;
822 wxFilterOutputStream::~wxFilterOutputStream()
826 // ----------------------------------------------------------------------------
827 // Some IOManip function
828 // ----------------------------------------------------------------------------
830 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
833 return stream
.Write("\r\n", 2);
835 return stream
.Write("\n", 1);