fix for uninit vars
[wxWidgets.git] / src / common / stream.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/stream.cpp
3 // Purpose: wxStream base classes
4 // Author: Guilhem Lavaux
5 // Modified by: VZ (23.11.00) to fix realloc()ing new[]ed memory,
6 // general code review
7 // Created: 11/07/98
8 // RCS-ID: $Id$
9 // Copyright: (c) Guilhem Lavaux
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 #ifdef __GNUG__
22 #pragma implementation "stream.h"
23 #endif
24
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
27
28 #ifdef __BORLANDC__
29 #pragma hdrstop
30 #endif
31
32 #ifndef WX_PRECOMP
33 #include "wx/defs.h"
34 #endif
35
36 #if wxUSE_STREAMS
37
38 #include <ctype.h>
39 #include "wx/stream.h"
40 #include "wx/datstrm.h"
41 #include "wx/objstrm.h"
42
43 // ----------------------------------------------------------------------------
44 // constants
45 // ----------------------------------------------------------------------------
46
47 // the temporary buffer size used when copying from stream to stream
48 #define BUF_TEMP_SIZE 10000
49
50 // ============================================================================
51 // implementation
52 // ============================================================================
53
54 // ----------------------------------------------------------------------------
55 // wxStreamBuffer
56 // ----------------------------------------------------------------------------
57
58 void wxStreamBuffer::SetError(wxStreamError err)
59 {
60 if ( m_stream->m_lasterror == wxStream_NOERROR )
61 m_stream->m_lasterror = err;
62 }
63
64 void wxStreamBuffer::InitBuffer()
65 {
66 m_buffer_start =
67 m_buffer_end =
68 m_buffer_pos = NULL;
69 m_buffer_size = 0;
70
71 // there is nothing to destroy anyhow
72 m_destroybuf = FALSE;
73 }
74
75 void wxStreamBuffer::Init()
76 {
77 InitBuffer();
78
79 m_fixed = TRUE;
80 }
81
82 wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
83 {
84 Init();
85
86 m_stream = &stream;
87 m_mode = mode;
88
89 m_flushable = TRUE;
90 m_destroystream = FALSE;
91 }
92
93 wxStreamBuffer::wxStreamBuffer(BufMode mode)
94 {
95 Init();
96
97 m_stream = new wxStreamBase;
98 m_mode = mode;
99
100 m_flushable = FALSE;
101 m_destroystream = TRUE;
102 }
103
104 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer)
105 {
106 // doing this has big chances to lead to a crashwhen the source buffer is
107 // destroyed (otherwise assume the caller knows what he does)
108 wxASSERT_MSG( !buffer.m_destroybuf && !buffer.m_destroystream,
109 _T("it's a bad idea to copy this buffer") );
110
111 m_buffer_start = buffer.m_buffer_start;
112 m_buffer_end = buffer.m_buffer_end;
113 m_buffer_pos = buffer.m_buffer_pos;
114 m_buffer_size = buffer.m_buffer_size;
115 m_fixed = buffer.m_fixed;
116 m_flushable = buffer.m_flushable;
117 m_stream = buffer.m_stream;
118 m_mode = buffer.m_mode;
119 m_destroybuf = FALSE;
120 m_destroystream = FALSE;
121 }
122
123 void wxStreamBuffer::FreeBuffer()
124 {
125 if ( m_destroybuf )
126 free(m_buffer_start);
127 }
128
129 wxStreamBuffer::~wxStreamBuffer()
130 {
131 FreeBuffer();
132
133 if ( m_destroystream )
134 delete m_stream;
135 }
136
137 wxInputStream *wxStreamBuffer::GetInputStream() const
138 {
139 return m_mode == write ? NULL : (wxInputStream *)m_stream;
140 }
141
142 wxOutputStream *wxStreamBuffer::GetOutputStream() const
143 {
144 return m_mode == read ? NULL : (wxOutputStream *)m_stream;
145 }
146
147 void wxStreamBuffer::SetBufferIO(void *buffer_start,
148 void *buffer_end,
149 bool takeOwnership)
150 {
151 SetBufferIO(buffer_start, (char *)buffer_end - (char *)buffer_start,
152 takeOwnership);
153 }
154
155 void wxStreamBuffer::SetBufferIO(void *start,
156 size_t len,
157 bool takeOwnership)
158 {
159 // start by freeing the old buffer
160 FreeBuffer();
161
162 m_buffer_start = (char *)start;
163 m_buffer_end = m_buffer_start + len;
164
165 m_buffer_size = len;
166
167 // if we own it, we free it
168 m_destroybuf = !takeOwnership;
169
170 ResetBuffer();
171 }
172
173 void wxStreamBuffer::SetBufferIO(size_t bufsize)
174 {
175 // start by freeing the old buffer
176 FreeBuffer();
177
178 if ( bufsize )
179 {
180 SetBufferIO(malloc(bufsize), bufsize, TRUE /* take ownership */);
181 }
182 else // no buffer size => no buffer
183 {
184 InitBuffer();
185 }
186 }
187
188 void wxStreamBuffer::ResetBuffer()
189 {
190 wxCHECK_RET( m_stream, _T("should have a stream in wxStreamBuffer") );
191
192 m_stream->m_lasterror = wxStream_NOERROR;
193 m_stream->m_lastcount = 0;
194 if (m_mode == read && m_flushable)
195 m_buffer_pos = m_buffer_end;
196 else
197 m_buffer_pos = m_buffer_start;
198 }
199
200 // fill the buffer with as much data as possible (only for read buffers)
201 bool wxStreamBuffer::FillBuffer()
202 {
203 wxInputStream *inStream = GetInputStream();
204
205 wxCHECK_MSG( inStream, FALSE, _T("should have a stream in wxStreamBuffer") );
206
207 size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size);
208 if ( !count )
209 return FALSE;
210
211 m_buffer_end = m_buffer_start + count;
212 m_buffer_pos = m_buffer_start;
213
214 return TRUE;
215 }
216
217 // write the buffer contents to the stream (only for write buffers)
218 bool wxStreamBuffer::FlushBuffer()
219 {
220 wxCHECK_MSG( m_flushable, FALSE, _T("can't flush this buffer") );
221
222 // FIXME: what is this check for? (VZ)
223 if ( m_buffer_pos == m_buffer_start )
224 return FALSE;
225
226 wxOutputStream *outStream = GetOutputStream();
227
228 wxCHECK_MSG( outStream, FALSE, _T("should have a stream in wxStreamBuffer") );
229
230 size_t current = m_buffer_pos - m_buffer_start;
231 size_t count = outStream->OnSysWrite(m_buffer_start, current);
232 if ( count != current )
233 return FALSE;
234
235 m_buffer_pos = m_buffer_start;
236
237 return TRUE;
238 }
239
240 size_t wxStreamBuffer::GetDataLeft()
241 {
242 /* Why is this done? RR. */
243 if ( m_buffer_pos == m_buffer_end && m_flushable)
244 FillBuffer();
245
246 return GetBytesLeft();
247 }
248
249 // copy up to size bytes from our buffer into the provided one
250 void wxStreamBuffer::GetFromBuffer(void *buffer, size_t size)
251 {
252 // don't get more bytes than left in the buffer
253 size_t left = GetBytesLeft();
254
255 if ( size > left )
256 size = left;
257
258 memcpy(buffer, m_buffer_pos, size);
259 m_buffer_pos += size;
260 }
261
262 // copy the contents of the provided buffer into this one
263 void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size)
264 {
265 size_t left = GetBytesLeft();
266 if ( size > left )
267 {
268 if ( m_fixed )
269 {
270 // we can't realloc the buffer, so just copy what we can
271 size = left;
272 }
273 else // !m_fixed
274 {
275 // realloc the buffer to have enough space for the data
276 size_t delta = m_buffer_pos - m_buffer_start;
277
278 char *startOld = m_buffer_start;
279 m_buffer_size += size;
280 m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size);
281 if ( !m_buffer_start )
282 {
283 // don't leak memory if realloc() failed
284 m_buffer_start = startOld;
285 m_buffer_size -= size;
286
287 // what else can we do?
288 return;
289 }
290
291 // adjust the pointers invalidated by realloc()
292 m_buffer_pos = m_buffer_start + delta;
293 m_buffer_end = m_buffer_start + m_buffer_size;
294 }
295 }
296
297 memcpy(m_buffer_pos, buffer, size);
298 m_buffer_pos += size;
299 }
300
301 void wxStreamBuffer::PutChar(char c)
302 {
303 wxOutputStream *outStream = GetOutputStream();
304
305 wxCHECK_RET( outStream, _T("should have a stream in wxStreamBuffer") );
306
307 // if we don't have buffer at all, just forward this call to the stream,
308 if ( !HasBuffer() )
309 {
310 outStream->OnSysWrite(&c, 1);
311 }
312 else
313 {
314 // otherwise check we have enough space left
315 if ( !GetDataLeft() && !FlushBuffer() )
316 {
317 // we don't
318 SetError(wxStream_WRITE_ERR);
319 }
320 else
321 {
322 PutToBuffer(&c, 1);
323 m_stream->m_lastcount = 1;
324 }
325 }
326 }
327
328 char wxStreamBuffer::Peek()
329 {
330 wxCHECK_MSG( m_stream && HasBuffer(), 0,
331 _T("should have the stream and the buffer in wxStreamBuffer") );
332
333 if ( !GetDataLeft() )
334 {
335 SetError(wxStream_READ_ERR);
336 return 0;
337 }
338
339 char c;
340 GetFromBuffer(&c, 1);
341 m_buffer_pos--;
342
343 return c;
344 }
345
346 char wxStreamBuffer::GetChar()
347 {
348 wxInputStream *inStream = GetInputStream();
349
350 wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") );
351
352 char c;
353 if ( !HasBuffer() )
354 {
355 inStream->OnSysRead(&c, 1);
356 }
357 else
358 {
359 if ( !GetDataLeft() )
360 {
361 SetError(wxStream_READ_ERR);
362 c = 0;
363 }
364 else
365 {
366 GetFromBuffer(&c, 1);
367 m_stream->m_lastcount = 1;
368 }
369 }
370
371 return c;
372 }
373
374 size_t wxStreamBuffer::Read(void *buffer, size_t size)
375 {
376 wxInputStream *inStream = GetInputStream();
377
378 wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") );
379
380 // lasterror is reset before all new IO calls
381 m_stream->m_lasterror = wxStream_NOERROR;
382
383 if ( !HasBuffer() )
384 {
385 m_stream->m_lastcount = inStream->OnSysRead(buffer, size);
386 }
387 else // we have a buffer, use it
388 {
389 size_t orig_size = size;
390
391 while ( size > 0 )
392 {
393 size_t left = GetDataLeft();
394
395 // if the requested number of bytes if greater than the buffer
396 // size, read data in chunks
397 if ( size > left )
398 {
399 GetFromBuffer(buffer, left);
400 size -= left;
401 buffer = (char *)buffer + left;
402
403 if ( !FillBuffer() )
404 {
405 SetError(wxStream_EOF);
406 break;
407 }
408 }
409 else // otherwise just do it in one gulp
410 {
411 GetFromBuffer(buffer, size);
412 size = 0;
413 }
414 }
415
416 m_stream->m_lastcount = orig_size - size;
417 }
418
419 return m_stream->m_lastcount;
420 }
421
422 // this should really be called "Copy()"
423 size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf)
424 {
425 wxCHECK_MSG( m_mode != write, 0, _T("can't read from this buffer") );
426
427 char buf[BUF_TEMP_SIZE];
428 size_t nRead,
429 total = 0;
430
431 do
432 {
433 nRead = Read(dbuf, WXSIZEOF(buf));
434 if ( nRead )
435 {
436 nRead = dbuf->Write(buf, nRead);
437 total += nRead;
438 }
439 }
440 while ( nRead );
441
442 return total;
443 }
444
445 size_t wxStreamBuffer::Write(const void *buffer, size_t size)
446 {
447 wxOutputStream *outStream = GetOutputStream();
448
449 wxCHECK_MSG( outStream, 0, _T("should have a stream in wxStreamBuffer") );
450
451 // lasterror is reset before all new IO calls
452 m_stream->m_lasterror = wxStream_NOERROR;
453
454 if ( !HasBuffer() && m_fixed )
455 {
456 // no buffer, just forward the call to the stream
457 m_stream->m_lastcount = outStream->OnSysWrite(buffer, size);
458 }
459 else // we [may] have a buffer, use it
460 {
461 size_t orig_size = size;
462
463 while ( size > 0 )
464 {
465 size_t left = GetBytesLeft();
466
467 // if the buffer is too large to fit in the stream buffer, split
468 // it in smaller parts
469 //
470 // NB: If stream buffer isn't fixed (as for wxMemoryOutputStream),
471 // we always go to the second case.
472 //
473 // FIXME: fine, but if it fails we should (re)try writing it by
474 // chunks as this will (hopefully) always work (VZ)
475 if ( size > left && m_fixed )
476 {
477 PutToBuffer(buffer, left);
478 size -= left;
479 buffer = (char *)buffer + left;
480
481 if ( !FlushBuffer() )
482 {
483 SetError(wxStream_WRITE_ERR);
484
485 break;
486 }
487
488 m_buffer_pos = m_buffer_start;
489 }
490 else // we can do it in one gulp
491 {
492 PutToBuffer(buffer, size);
493 size = 0;
494 }
495 }
496
497 m_stream->m_lastcount = orig_size - size;
498 }
499
500 return m_stream->m_lastcount;
501 }
502
503 size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
504 {
505 wxCHECK_MSG( m_mode != read, 0, _T("can't write to this buffer") );
506 wxCHECK_MSG( sbuf->m_mode != write, 0, _T("can't read from that buffer") );
507
508 char buf[BUF_TEMP_SIZE];
509 size_t nWrite,
510 total = 0;
511
512 do
513 {
514 size_t nRead = sbuf->Read(buf, WXSIZEOF(buf));
515 if ( nRead )
516 {
517 nWrite = Write(buf, nRead);
518 if ( nWrite < nRead )
519 {
520 // put back data we couldn't copy
521 wxInputStream *in_stream = (wxInputStream *)sbuf->GetStream();
522
523 in_stream->Ungetch(buf + nWrite, nRead - nWrite);
524 }
525
526 total += nWrite;
527 }
528 else
529 {
530 nWrite = 0;
531 }
532 }
533 while ( nWrite == WXSIZEOF(buf) );
534
535 return total;
536 }
537
538 off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
539 {
540 off_t ret_off, diff;
541
542 off_t last_access = GetLastAccess();
543
544 if ( !m_flushable )
545 {
546 switch (mode)
547 {
548 case wxFromStart:
549 diff = pos;
550 break;
551
552 case wxFromCurrent:
553 diff = pos + GetIntPosition();
554 break;
555
556 case wxFromEnd:
557 diff = pos + last_access;
558 break;
559
560 default:
561 wxFAIL_MSG( _T("invalid seek mode") );
562
563 return wxInvalidOffset;
564 }
565 if (diff < 0 || diff > last_access)
566 return wxInvalidOffset;
567 SetIntPosition(diff);
568 return diff;
569 }
570
571 switch ( mode )
572 {
573 case wxFromStart:
574 // We'll try to compute an internal position later ...
575 ret_off = m_stream->OnSysSeek(pos, wxFromStart);
576 ResetBuffer();
577 return ret_off;
578
579 case wxFromCurrent:
580 diff = pos + GetIntPosition();
581
582 if ( (diff > last_access) || (diff < 0) )
583 {
584 // We must take into account the fact that we have read
585 // something previously.
586 ret_off = m_stream->OnSysSeek(diff-last_access, wxFromCurrent);
587 ResetBuffer();
588 return ret_off;
589 }
590 else
591 {
592 SetIntPosition(diff);
593 return pos;
594 }
595
596 case wxFromEnd:
597 // Hard to compute: always seek to the requested position.
598 ret_off = m_stream->OnSysSeek(pos, wxFromEnd);
599 ResetBuffer();
600 return ret_off;
601 }
602
603 return wxInvalidOffset;
604 }
605
606 off_t wxStreamBuffer::Tell() const
607 {
608 off_t pos = m_stream->OnSysTell();
609 if ( pos == wxInvalidOffset )
610 return wxInvalidOffset;
611
612 pos += GetIntPosition();
613
614 if ( m_mode == read && m_flushable )
615 pos -= GetLastAccess();
616
617 return pos;
618 }
619
620 // ----------------------------------------------------------------------------
621 // wxStreamBase
622 // ----------------------------------------------------------------------------
623
624 wxStreamBase::wxStreamBase()
625 {
626 m_lasterror = wxStream_NOERROR;
627 m_lastcount = 0;
628 }
629
630 wxStreamBase::~wxStreamBase()
631 {
632 }
633
634 off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode))
635 {
636 return wxInvalidOffset;
637 }
638
639 off_t wxStreamBase::OnSysTell() const
640 {
641 return wxInvalidOffset;
642 }
643
644 // ----------------------------------------------------------------------------
645 // wxInputStream
646 // ----------------------------------------------------------------------------
647
648 wxInputStream::wxInputStream()
649 {
650 m_wback = NULL;
651 m_wbacksize =
652 m_wbackcur = 0;
653 }
654
655 wxInputStream::~wxInputStream()
656 {
657 free(m_wback);
658 }
659
660 size_t wxInputStream::OnSysRead(void * WXUNUSED(buffer),
661 size_t WXUNUSED(bufsize))
662 {
663 return 0;
664 }
665
666 bool wxInputStream::Eof() const
667 {
668 wxInputStream *self = wxConstCast(this, wxInputStream);
669
670 char c;
671 self->Read(&c, 1);
672 if ( GetLastError() == wxSTREAM_EOF )
673 {
674 return TRUE;
675 }
676
677 self->Ungetch(c);
678
679 return FALSE;
680 }
681
682 char *wxInputStream::AllocSpaceWBack(size_t needed_size)
683 {
684 // get number of bytes left from previous wback buffer
685 size_t toget = m_wbacksize - m_wbackcur;
686
687 // allocate a buffer large enough to hold prev + new data
688 char *temp_b = (char *)malloc(needed_size + toget);
689
690 if (!temp_b)
691 return NULL;
692
693 /* copy previous data (and free old buffer) if needed */
694 if (m_wback)
695 {
696 memmove(temp_b + needed_size, m_wback + m_wbackcur, toget);
697 free(m_wback);
698 }
699
700 /* done */
701 m_wback = temp_b;
702 m_wbackcur = 0;
703 m_wbacksize = needed_size + toget;
704
705 return m_wback;
706 }
707
708 size_t wxInputStream::GetWBack(void *buf, size_t bsize)
709 {
710 size_t toget = m_wbacksize-m_wbackcur;
711
712 if (!m_wback)
713 return 0;
714
715 if (bsize < toget)
716 toget = bsize;
717
718 memcpy(buf, (m_wback+m_wbackcur), toget);
719
720 m_wbackcur += toget;
721 if (m_wbackcur == m_wbacksize)
722 {
723 free(m_wback);
724 m_wback = NULL;
725 m_wbacksize = 0;
726 m_wbackcur = 0;
727 }
728
729 return toget;
730 }
731
732 size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
733 {
734 char *ptrback = AllocSpaceWBack(bufsize);
735 if (!ptrback)
736 return 0;
737
738 memcpy(ptrback, buf, bufsize);
739 return bufsize;
740 }
741
742 bool wxInputStream::Ungetch(char c)
743 {
744 void *ptrback = AllocSpaceWBack(1);
745 if (!ptrback)
746 return FALSE;
747
748 *(char *)ptrback = c;
749 return TRUE;
750 }
751
752 char wxInputStream::GetC()
753 {
754 char c;
755 Read(&c, 1);
756 return c;
757 }
758
759 wxInputStream& wxInputStream::Read(void *buf, size_t size)
760 {
761 size_t retsize = GetWBack(buf, size);
762 if (retsize == size)
763 {
764 m_lastcount = size;
765 m_lasterror = wxStream_NOERROR;
766 return *this;
767 }
768 size -= retsize;
769 buf = (char *)buf + retsize;
770
771 m_lastcount = OnSysRead(buf, size) + retsize;
772 return *this;
773 }
774
775 char wxInputStream::Peek()
776 {
777 char c;
778 Read(&c, 1);
779 if (m_lasterror == wxStream_NOERROR)
780 {
781 Ungetch(c);
782 return c;
783 }
784
785 return 0;
786 }
787
788 wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
789 {
790 char buf[BUF_TEMP_SIZE];
791 size_t bytes_read = BUF_TEMP_SIZE;
792
793 while (bytes_read == BUF_TEMP_SIZE)
794 {
795 bytes_read = Read(buf, bytes_read).LastRead();
796 bytes_read = stream_out.Write(buf, bytes_read).LastWrite();
797 }
798 return *this;
799 }
800
801 off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
802 {
803 /* Should be check and improve, just to remove a slight bug !
804 I don't know whether it should be put as well in wxFileInputStream::OnSysSeek ? */
805 if (m_lasterror==wxSTREAM_EOF)
806 m_lasterror=wxSTREAM_NOERROR;
807
808 /* A call to SeekI() will automatically invalidate any previous call
809 to Ungetch(), otherwise it would be possible to SeekI() to one
810 one position, unread some bytes there, SeekI() to another position
811 and the data would be corrupted.
812
813 GRG: Could add code here to try to navigate within the wback
814 buffer if possible, but is it really needed? It would only work
815 when seeking in wxFromCurrent mode, else it would invalidate
816 anyway...
817 */
818 if (m_wback)
819 {
820 free(m_wback);
821 m_wback = NULL;
822 m_wbacksize = 0;
823 m_wbackcur = 0;
824 }
825
826 return OnSysSeek(pos, mode);
827 }
828
829 off_t wxInputStream::TellI() const
830 {
831 /* GRG: Changed to make it compatible with the wback buffer */
832 off_t pos = OnSysTell();
833
834 if (pos != wxInvalidOffset)
835 pos -= (m_wbacksize - m_wbackcur);
836
837 return pos;
838 }
839
840 // --------------------
841 // Overloaded operators
842 // --------------------
843
844 #if wxUSE_SERIAL
845 wxInputStream& wxInputStream::operator>>(wxObject *& obj)
846 {
847 wxObjectInputStream obj_s(*this);
848 obj = obj_s.LoadObject();
849 return *this;
850 }
851 #endif // wxUSE_SERIAL
852
853
854 // ----------------------------------------------------------------------------
855 // wxOutputStream
856 // ----------------------------------------------------------------------------
857
858 wxOutputStream::wxOutputStream()
859 {
860 }
861
862 wxOutputStream::~wxOutputStream()
863 {
864 }
865
866 size_t wxOutputStream::OnSysWrite(const void * WXUNUSED(buffer),
867 size_t WXUNUSED(bufsize))
868 {
869 return 0;
870 }
871
872 void wxOutputStream::PutC(char c)
873 {
874 Write(&c, 1);
875 }
876
877 wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
878 {
879 m_lastcount = OnSysWrite(buffer, size);
880 return *this;
881 }
882
883 wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
884 {
885 stream_in.Read(*this);
886 return *this;
887 }
888
889 off_t wxOutputStream::TellO() const
890 {
891 return OnSysTell();
892 }
893
894 off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
895 {
896 return OnSysSeek(pos, mode);
897 }
898
899 void wxOutputStream::Sync()
900 {
901 }
902
903 #if wxUSE_SERIAL
904 wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
905 {
906 wxObjectOutputStream obj_s(*this);
907 obj_s.SaveObject(obj);
908 return *this;
909 }
910 #endif // wxUSE_SERIAL
911
912 // ----------------------------------------------------------------------------
913 // wxCountingOutputStream
914 // ----------------------------------------------------------------------------
915
916 wxCountingOutputStream::wxCountingOutputStream ()
917 {
918 m_currentPos = 0;
919 }
920
921 size_t wxCountingOutputStream::GetSize() const
922 {
923 return m_lastcount;
924 }
925
926 size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer),
927 size_t size)
928 {
929 m_currentPos += size;
930 if (m_currentPos > m_lastcount)
931 m_lastcount = m_currentPos;
932
933 return m_currentPos;
934 }
935
936 off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
937 {
938 switch ( mode )
939 {
940 case wxFromStart:
941 m_currentPos = pos;
942 break;
943
944 case wxFromEnd:
945 m_currentPos = m_lastcount + pos;
946 break;
947
948 case wxFromCurrent:
949 m_currentPos += pos;
950 break;
951
952 default:
953 wxFAIL_MSG( _T("invalid seek mode") );
954 return wxInvalidOffset;
955 }
956
957 if (m_currentPos > m_lastcount)
958 m_lastcount = m_currentPos;
959
960 return m_currentPos;
961 }
962
963 off_t wxCountingOutputStream::OnSysTell() const
964 {
965 return m_currentPos;
966 }
967
968 // ----------------------------------------------------------------------------
969 // wxFilterInputStream
970 // ----------------------------------------------------------------------------
971
972 wxFilterInputStream::wxFilterInputStream()
973 {
974 m_parent_i_stream = NULL;
975 }
976
977 wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
978 {
979 m_parent_i_stream = &stream;
980 }
981
982 wxFilterInputStream::~wxFilterInputStream()
983 {
984 }
985
986 // ----------------------------------------------------------------------------
987 // wxFilterOutputStream
988 // ----------------------------------------------------------------------------
989
990 wxFilterOutputStream::wxFilterOutputStream()
991 {
992 m_parent_o_stream = NULL;
993 }
994
995 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
996 {
997 m_parent_o_stream = &stream;
998 }
999
1000 wxFilterOutputStream::~wxFilterOutputStream()
1001 {
1002 }
1003
1004 // ----------------------------------------------------------------------------
1005 // wxBufferedInputStream
1006 // ----------------------------------------------------------------------------
1007
1008 wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s,
1009 wxStreamBuffer *buffer)
1010 : wxFilterInputStream(s)
1011 {
1012 if ( buffer )
1013 {
1014 // use the buffer provided by the user
1015 m_i_streambuf = buffer;
1016 }
1017 else // create a default buffer
1018 {
1019 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
1020
1021 m_i_streambuf->SetBufferIO(1024);
1022 }
1023 }
1024
1025 wxBufferedInputStream::~wxBufferedInputStream()
1026 {
1027 m_parent_i_stream->SeekI(-m_i_streambuf->GetBytesLeft(), wxFromCurrent);
1028
1029 delete m_i_streambuf;
1030 }
1031
1032 char wxBufferedInputStream::Peek()
1033 {
1034 return m_i_streambuf->Peek();
1035 }
1036
1037 wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
1038 {
1039 size_t retsize;
1040
1041 retsize = GetWBack(buf, size);
1042 m_lastcount = retsize;
1043 if ( retsize == size )
1044 {
1045 m_lasterror = wxStream_NOERROR;
1046 return *this;
1047 }
1048 size -= retsize;
1049 buf = (char *)buf + retsize;
1050
1051 m_i_streambuf->Read(buf, size);
1052
1053 return *this;
1054 }
1055
1056 off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
1057 {
1058 return m_i_streambuf->Seek(pos, mode);
1059 }
1060
1061 off_t wxBufferedInputStream::TellI() const
1062 {
1063 return m_i_streambuf->Tell();
1064 }
1065
1066 size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
1067 {
1068 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
1069 }
1070
1071 off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
1072 {
1073 return m_parent_i_stream->SeekI(seek, mode);
1074 }
1075
1076 off_t wxBufferedInputStream::OnSysTell() const
1077 {
1078 return m_parent_i_stream->TellI();
1079 }
1080
1081 void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer *buffer)
1082 {
1083 wxCHECK_RET( buffer, _T("wxBufferedInputStream needs buffer") );
1084
1085 delete m_i_streambuf;
1086 m_i_streambuf = buffer;
1087 }
1088
1089 // ----------------------------------------------------------------------------
1090 // wxBufferedOutputStream
1091 // ----------------------------------------------------------------------------
1092
1093 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s,
1094 wxStreamBuffer *buffer)
1095 : wxFilterOutputStream(s)
1096 {
1097 if ( buffer )
1098 {
1099 m_o_streambuf = buffer;
1100 }
1101 else // create a default one
1102 {
1103 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
1104
1105 m_o_streambuf->SetBufferIO(1024);
1106 }
1107 }
1108
1109 wxBufferedOutputStream::~wxBufferedOutputStream()
1110 {
1111 Sync();
1112 delete m_o_streambuf;
1113 }
1114
1115 wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
1116 {
1117 m_lastcount = 0;
1118 m_o_streambuf->Write(buffer, size);
1119 return *this;
1120 }
1121
1122 off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
1123 {
1124 Sync();
1125 return m_o_streambuf->Seek(pos, mode);
1126 }
1127
1128 off_t wxBufferedOutputStream::TellO() const
1129 {
1130 return m_o_streambuf->Tell();
1131 }
1132
1133 void wxBufferedOutputStream::Sync()
1134 {
1135 m_o_streambuf->FlushBuffer();
1136 m_parent_o_stream->Sync();
1137 }
1138
1139 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
1140 {
1141 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
1142 }
1143
1144 off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
1145 {
1146 return m_parent_o_stream->SeekO(seek, mode);
1147 }
1148
1149 off_t wxBufferedOutputStream::OnSysTell() const
1150 {
1151 return m_parent_o_stream->TellO();
1152 }
1153
1154 size_t wxBufferedOutputStream::GetSize() const
1155 {
1156 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
1157 }
1158
1159 void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer)
1160 {
1161 wxCHECK_RET( buffer, _T("wxBufferedOutputStream needs buffer") );
1162
1163 delete m_o_streambuf;
1164 m_o_streambuf = buffer;
1165 }
1166
1167 // ----------------------------------------------------------------------------
1168 // Some IOManip function
1169 // ----------------------------------------------------------------------------
1170
1171 wxOutputStream& wxEndL(wxOutputStream& stream)
1172 {
1173 #ifdef __MSW__
1174 return stream.Write("\r\n", 2);
1175 #else
1176 #ifdef __WXMAC__
1177 return stream.Write("\r", 1);
1178 #else
1179 return stream.Write("\n", 1);
1180 #endif
1181 #endif
1182 }
1183
1184 #endif
1185 // wxUSE_STREAMS