wxSetEnv for Win32 (doesn't really work)
[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(-(off_t)m_i_streambuf->GetBytesLeft(),
1028 wxFromCurrent);
1029
1030 delete m_i_streambuf;
1031 }
1032
1033 char wxBufferedInputStream::Peek()
1034 {
1035 return m_i_streambuf->Peek();
1036 }
1037
1038 wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
1039 {
1040 size_t retsize;
1041
1042 retsize = GetWBack(buf, size);
1043 m_lastcount = retsize;
1044 if ( retsize == size )
1045 {
1046 m_lasterror = wxStream_NOERROR;
1047 return *this;
1048 }
1049 size -= retsize;
1050 buf = (char *)buf + retsize;
1051
1052 m_i_streambuf->Read(buf, size);
1053
1054 return *this;
1055 }
1056
1057 off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
1058 {
1059 return m_i_streambuf->Seek(pos, mode);
1060 }
1061
1062 off_t wxBufferedInputStream::TellI() const
1063 {
1064 return m_i_streambuf->Tell();
1065 }
1066
1067 size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
1068 {
1069 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
1070 }
1071
1072 off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
1073 {
1074 return m_parent_i_stream->SeekI(seek, mode);
1075 }
1076
1077 off_t wxBufferedInputStream::OnSysTell() const
1078 {
1079 return m_parent_i_stream->TellI();
1080 }
1081
1082 void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer *buffer)
1083 {
1084 wxCHECK_RET( buffer, _T("wxBufferedInputStream needs buffer") );
1085
1086 delete m_i_streambuf;
1087 m_i_streambuf = buffer;
1088 }
1089
1090 // ----------------------------------------------------------------------------
1091 // wxBufferedOutputStream
1092 // ----------------------------------------------------------------------------
1093
1094 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s,
1095 wxStreamBuffer *buffer)
1096 : wxFilterOutputStream(s)
1097 {
1098 if ( buffer )
1099 {
1100 m_o_streambuf = buffer;
1101 }
1102 else // create a default one
1103 {
1104 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
1105
1106 m_o_streambuf->SetBufferIO(1024);
1107 }
1108 }
1109
1110 wxBufferedOutputStream::~wxBufferedOutputStream()
1111 {
1112 Sync();
1113 delete m_o_streambuf;
1114 }
1115
1116 wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
1117 {
1118 m_lastcount = 0;
1119 m_o_streambuf->Write(buffer, size);
1120 return *this;
1121 }
1122
1123 off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
1124 {
1125 Sync();
1126 return m_o_streambuf->Seek(pos, mode);
1127 }
1128
1129 off_t wxBufferedOutputStream::TellO() const
1130 {
1131 return m_o_streambuf->Tell();
1132 }
1133
1134 void wxBufferedOutputStream::Sync()
1135 {
1136 m_o_streambuf->FlushBuffer();
1137 m_parent_o_stream->Sync();
1138 }
1139
1140 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
1141 {
1142 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
1143 }
1144
1145 off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
1146 {
1147 return m_parent_o_stream->SeekO(seek, mode);
1148 }
1149
1150 off_t wxBufferedOutputStream::OnSysTell() const
1151 {
1152 return m_parent_o_stream->TellO();
1153 }
1154
1155 size_t wxBufferedOutputStream::GetSize() const
1156 {
1157 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
1158 }
1159
1160 void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer)
1161 {
1162 wxCHECK_RET( buffer, _T("wxBufferedOutputStream needs buffer") );
1163
1164 delete m_o_streambuf;
1165 m_o_streambuf = buffer;
1166 }
1167
1168 // ----------------------------------------------------------------------------
1169 // Some IOManip function
1170 // ----------------------------------------------------------------------------
1171
1172 wxOutputStream& wxEndL(wxOutputStream& stream)
1173 {
1174 #ifdef __MSW__
1175 return stream.Write("\r\n", 2);
1176 #else
1177 #ifdef __WXMAC__
1178 return stream.Write("\r", 1);
1179 #else
1180 return stream.Write("\n", 1);
1181 #endif
1182 #endif
1183 }
1184
1185 #endif
1186 // wxUSE_STREAMS