]>
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 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
31 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
)
32 : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
),
33 m_buffer_size(0), m_stream(&stream
), m_mode(mode
)
37 wxStreamBuffer::~wxStreamBuffer()
39 wxDELETEA(m_buffer_start
);
42 bool wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
)
46 ptrback
= AllocSpaceWBack(bufsize
);
50 memcpy(ptrback
, buf
, bufsize
);
54 bool wxStreamBuffer::WriteBack(char c
)
58 ptrback
= AllocSpaceWBack(1);
66 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
)
68 m_buffer_start
= buffer_start
;
69 m_buffer_end
= buffer_end
;
71 m_buffer_size
= m_buffer_end
-m_buffer_start
;
75 void wxStreamBuffer::SetBufferIO(size_t bufsize
)
79 wxDELETE(m_buffer_start
);
82 m_buffer_start
= NULL
;
89 b_start
= new char[bufsize
];
91 SetBufferIO(b_start
, b_start
+ bufsize
);
94 void wxStreamBuffer::ResetBuffer()
97 m_buffer_pos
= m_buffer_end
;
99 m_buffer_pos
= m_buffer_start
;
102 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
)
106 m_wbacksize
+= needed_size
;
109 temp_b
= (char *)malloc(m_wbacksize
);
111 temp_b
= (char *)realloc(m_wback
, m_wbacksize
);
115 return (char *)((size_t)m_wback
+(m_wbacksize
-needed_size
));
118 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
)
120 size_t s_toget
= m_wbacksize
-m_wbackcur
;
125 memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
);
127 m_wbackcur
+= s_toget
;
128 if (m_wbackcur
== m_wbacksize
) {
130 m_wback
= (char *)NULL
;
138 bool wxStreamBuffer::FillBuffer()
142 count
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
);
143 m_buffer_end
= m_buffer_start
+count
;
144 m_buffer_pos
= m_buffer_start
;
151 bool wxStreamBuffer::FlushBuffer()
153 size_t count
, current
;
155 if (m_buffer_pos
== m_buffer_start
)
158 current
= m_buffer_pos
-m_buffer_start
;
159 count
= m_stream
->OnSysWrite(m_buffer_start
, current
);
160 if (count
!= current
)
162 m_buffer_pos
= m_buffer_start
;
167 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
)
169 size_t s_toget
= m_buffer_end
-m_buffer_pos
;
174 memcpy(buffer
, m_buffer_pos
, s_toget
);
175 m_buffer_pos
+= s_toget
;
178 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
)
180 size_t s_toput
= m_buffer_end
-m_buffer_pos
;
182 if (s_toput
< size
&& !m_fixed
) {
183 m_buffer_start
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
);
185 m_buffer_end
= m_buffer_start
+m_buffer_size
;
190 memcpy(m_buffer_pos
, buffer
, s_toput
);
191 m_buffer_pos
+= s_toput
;
194 void wxStreamBuffer::Read(void *buffer
, size_t size
)
196 wxASSERT(m_stream
!= NULL
);
198 // ------------------
199 // Buffering disabled
200 // ------------------
202 m_stream
->m_lastcount
= GetWBack((char *)buffer
, size
);
203 size
-= m_stream
->m_lastcount
;
207 buffer
= (void *)((char *)buffer
+m_stream
->m_lastcount
);
209 if (!m_buffer_size
) {
210 m_stream
->m_lastcount
+= m_stream
->OnSysRead(buffer
, size
);
217 size_t buf_left
, orig_size
= size
;
220 buf_left
= GetDataLeft();
222 // First case: the requested buffer is larger than the stream buffer,
224 if (size
> buf_left
) {
225 GetFromBuffer(buffer
, buf_left
);
227 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
230 m_stream
->m_lastcount
= orig_size
-size
;
235 // Second case: we just copy from the stream buffer.
236 GetFromBuffer(buffer
, size
);
240 m_stream
->m_lastcount
+= orig_size
;
243 void wxStreamBuffer::Write(const void *buffer
, size_t size
)
245 wxASSERT(m_stream
!= NULL
);
247 // ------------------
248 // Buffering disabled
249 // ------------------
251 if (!m_buffer_size
) {
252 m_stream
->m_lastcount
= m_stream
->OnSysWrite(buffer
, size
);
256 // ------------------
258 // ------------------
260 size_t buf_left
, orig_size
= size
;
263 buf_left
= m_buffer_end
- m_buffer_pos
;
265 // First case: the buffer to write is larger than the stream buffer,
267 if (size
> buf_left
) {
268 PutToBuffer(buffer
, buf_left
);
270 buffer
= (char *)buffer
+ buf_left
; // ANSI C++ violation.
272 if (!FlushBuffer()) {
273 m_stream
->m_lastcount
= orig_size
-size
;
276 m_buffer_pos
= m_buffer_start
;
280 // Second case: just copy it in the stream buffer.
281 PutToBuffer(buffer
, size
);
285 m_stream
->m_lastcount
= orig_size
;
288 off_t
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
)
290 off_t ret_off
, diff
, last_access
;
292 last_access
= GetLastAccess();
296 // We'll try to compute an internal position later ...
297 ret_off
= m_stream
->OnSysSeek(pos
, wxFromStart
);
301 case wxFromCurrent
: {
302 diff
= pos
+ GetIntPosition();
304 if ( (diff
> last_access
) || (diff
< 0) ) {
305 ret_off
= m_stream
->OnSysSeek(pos
, wxFromCurrent
);
309 SetIntPosition(diff
);
314 // Hard to compute: always seek to the requested position.
315 ret_off
= m_stream
->OnSysSeek(pos
, wxFromEnd
);
319 return wxInvalidOffset
;
322 off_t
wxStreamBuffer::Tell() const
326 pos
= m_stream
->OnSysTell();
327 if (pos
== wxInvalidOffset
)
328 return wxInvalidOffset
;
330 return pos
- GetLastAccess() + GetIntPosition();
333 size_t wxStreamBuffer::GetDataLeft() const
335 return m_buffer_end
-m_buffer_pos
;
338 // ----------------------------------------------------------------------------
340 // ----------------------------------------------------------------------------
342 wxStreamBase::wxStreamBase()
344 m_lasterror
= wxStream_NOERROR
;
348 wxStreamBase::~wxStreamBase()
352 size_t wxStreamBase::OnSysRead(void *buffer
, size_t size
)
357 size_t wxStreamBase::OnSysWrite(const void *buffer
, size_t bufsize
)
362 off_t
wxStreamBase::OnSysSeek(off_t seek
, wxSeekMode mode
)
364 return wxInvalidOffset
;
367 off_t
wxStreamBase::OnSysTell()
369 return wxInvalidOffset
;
372 // ----------------------------------------------------------------------------
374 // ----------------------------------------------------------------------------
376 wxInputStream::wxInputStream()
379 m_i_destroybuf
= TRUE
;
380 m_i_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::read
);
383 wxInputStream::wxInputStream(wxStreamBuffer
*buffer
)
386 m_i_destroybuf
= FALSE
;
387 m_i_streambuf
= buffer
;
390 wxInputStream::~wxInputStream()
393 delete m_i_streambuf
;
396 char wxInputStream::GetC()
399 m_i_streambuf
->Read(&c
, 1);
403 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
)
405 m_i_streambuf
->Read(buffer
, size
);
406 // wxStreamBuffer sets all variables for us
410 char wxInputStream::Peek()
412 if (!m_i_streambuf
->GetDataLeft())
413 m_i_streambuf
->FillBuffer();
415 return *(m_i_streambuf
->GetBufferPos());
418 #define BUF_TEMP_SIZE 10000
420 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
)
422 char buf
[BUF_TEMP_SIZE
];
423 size_t bytes_read
= BUF_TEMP_SIZE
;
425 while (bytes_read
== BUF_TEMP_SIZE
&& stream_out
.LastError() != wxStream_NOERROR
) {
426 bytes_read
= Read(buf
, bytes_read
).LastRead();
428 stream_out
.Write(buf
, bytes_read
);
433 off_t
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
)
435 return m_i_streambuf
->Seek(pos
, mode
);
438 off_t
wxInputStream::TellI() const
440 return m_i_streambuf
->Tell();
443 // --------------------
444 // Overloaded operators
445 // --------------------
447 wxInputStream
& wxInputStream::operator>>(wxString
& line
)
449 wxDataInputStream
s(*this);
455 wxInputStream
& wxInputStream::operator>>(char& c
)
461 wxInputStream
& wxInputStream::operator>>(short& i
)
470 wxInputStream
& wxInputStream::operator>>(int& i
)
479 wxInputStream
& wxInputStream::operator>>(long& i
)
481 /* I only implemented a simple integer parser */
484 while (isspace( c
= GetC() ) )
488 if (! (c
== '-' || isdigit(c
)) ) {
489 InputStreamBuffer()->WriteBack(c
);
509 wxInputStream
& wxInputStream::operator>>(double& f
)
511 /* I only implemented a simple float parser */
514 while (isspace( c
= GetC() ) )
518 if (! (c
== '-' || isdigit(c
)) ) {
519 InputStreamBuffer()->WriteBack(c
);
530 f
= f
*10 + (c
- '0');
535 double f_multiplicator
= (double) 0.1;
539 f
+= (c
-'0')*f_multiplicator
;
540 f_multiplicator
/= 10;
551 wxInputStream
& wxInputStream::operator>>(wxObject
*& obj
)
553 wxObjectInputStream
obj_s(*this);
554 obj
= obj_s
.LoadObject();
560 // ----------------------------------------------------------------------------
562 // ----------------------------------------------------------------------------
563 wxOutputStream::wxOutputStream()
566 m_o_destroybuf
= TRUE
;
567 m_o_streambuf
= new wxStreamBuffer(*this, wxStreamBuffer::write
);
570 wxOutputStream::wxOutputStream(wxStreamBuffer
*buffer
)
573 m_o_destroybuf
= FALSE
;
574 m_o_streambuf
= buffer
;
577 wxOutputStream::~wxOutputStream()
580 delete m_o_streambuf
;
583 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
)
585 m_o_streambuf
->Write(buffer
, size
);
589 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
)
591 stream_in
.Read(*this);
595 off_t
wxOutputStream::TellO() const
597 return m_o_streambuf
->Tell();
600 off_t
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
)
602 return m_o_streambuf
->Seek(pos
, mode
);
605 void wxOutputStream::Sync()
607 m_o_streambuf
->FlushBuffer();
610 wxOutputStream
& wxOutputStream::operator<<(const char *string
)
612 return Write(string
, strlen(string
));
615 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
)
617 return Write(string
, string
.Len());
620 wxOutputStream
& wxOutputStream::operator<<(char c
)
625 wxOutputStream
& wxOutputStream::operator<<(short i
)
629 strint
.Printf("%i", i
);
630 return Write(strint
, strint
.Len());
633 wxOutputStream
& wxOutputStream::operator<<(int i
)
637 strint
.Printf("%i", i
);
638 return Write(strint
, strint
.Len());
641 wxOutputStream
& wxOutputStream::operator<<(long i
)
645 strlong
.Printf("%i", i
);
646 return Write((const char *)strlong
, strlong
.Len());
649 wxOutputStream
& wxOutputStream::operator<<(double f
)
653 strfloat
.Printf("%f", f
);
654 return Write(strfloat
, strfloat
.Len());
658 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
)
660 wxObjectOutputStream
obj_s(*this);
661 obj_s
.SaveObject(obj
);
666 // ----------------------------------------------------------------------------
667 // wxFilterInputStream
668 // ----------------------------------------------------------------------------
669 wxFilterInputStream::wxFilterInputStream()
670 : wxInputStream(NULL
)
672 // WARNING streambuf set to NULL !
675 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
)
676 : wxInputStream(stream
.InputStreamBuffer())
678 m_parent_i_stream
= &stream
;
681 wxFilterInputStream::~wxFilterInputStream()
685 // ----------------------------------------------------------------------------
686 // wxFilterOutputStream
687 // ----------------------------------------------------------------------------
688 wxFilterOutputStream::wxFilterOutputStream()
689 : wxOutputStream(NULL
)
693 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
)
694 : wxOutputStream(stream
.OutputStreamBuffer())
696 m_parent_o_stream
= &stream
;
699 wxFilterOutputStream::~wxFilterOutputStream()
703 // ----------------------------------------------------------------------------
704 // Some IOManip function
705 // ----------------------------------------------------------------------------
707 wxOutputStream
& wxEndL(wxOutputStream
& stream
)
710 return stream
.Write("\r\n", 2);
712 return stream
.Write("\n", 1);