Tell is now compatible with the wback buffer
[wxWidgets.git] / src / common / stream.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: stream.cpp
3 // Purpose: wxStream base classes
4 // Author: Guilhem Lavaux
5 // Modified by:
6 // Created: 11/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "stream.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #endif
26
27 #if wxUSE_STREAMS
28
29 #include <ctype.h>
30 #include "wx/stream.h"
31 #include "wx/datstrm.h"
32 #include "wx/objstrm.h"
33
34 #define BUF_TEMP_SIZE 10000
35
36 // ----------------------------------------------------------------------------
37 // wxStreamBuffer
38 // ----------------------------------------------------------------------------
39
40 #define CHECK_ERROR(err) \
41 if (m_stream->m_lasterror == wxStream_NOERROR) \
42 m_stream->m_lasterror = err
43
44 wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, 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(TRUE), m_stream(&stream),
47 m_mode(mode), m_destroybuf(FALSE), m_destroystream(FALSE)
48 {
49 }
50
51 wxStreamBuffer::wxStreamBuffer(BufMode mode)
52 : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
53 m_buffer_size(0), m_fixed(TRUE), m_flushable(FALSE), m_stream(NULL),
54 m_mode(mode), m_destroybuf(FALSE), m_destroystream(TRUE)
55 {
56 m_stream = new wxStreamBase();
57 }
58
59 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer)
60 {
61 m_buffer_start = buffer.m_buffer_start;
62 m_buffer_end = buffer.m_buffer_end;
63 m_buffer_pos = buffer.m_buffer_pos;
64 m_buffer_size = buffer.m_buffer_size;
65 m_fixed = buffer.m_fixed;
66 m_flushable = buffer.m_flushable;
67 m_stream = buffer.m_stream;
68 m_mode = buffer.m_mode;
69 m_destroybuf = FALSE;
70 m_destroystream = FALSE;
71 }
72
73 wxStreamBuffer::~wxStreamBuffer()
74 {
75 if (m_destroybuf)
76 wxDELETEA(m_buffer_start);
77 if (m_destroystream)
78 delete m_stream;
79 }
80
81 void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end)
82 {
83 if (m_destroybuf)
84 wxDELETEA(m_buffer_start);
85 m_buffer_start = buffer_start;
86 m_buffer_end = buffer_end;
87
88 m_buffer_size = m_buffer_end-m_buffer_start;
89 m_destroybuf = FALSE;
90 ResetBuffer();
91 }
92
93 void wxStreamBuffer::SetBufferIO(size_t bufsize)
94 {
95 char *b_start;
96
97 if (m_destroybuf)
98 wxDELETEA(m_buffer_start);
99
100 if (!bufsize) {
101 m_buffer_start = (char*)NULL;
102 m_buffer_end = (char*)NULL;
103 m_buffer_pos = (char*)NULL;
104 m_buffer_size = 0;
105 return;
106 }
107
108 b_start = new char[bufsize];
109 SetBufferIO(b_start, b_start + bufsize);
110 m_destroybuf = TRUE;
111 }
112
113 void wxStreamBuffer::ResetBuffer()
114 {
115 m_stream->m_lasterror = wxStream_NOERROR;
116 m_stream->m_lastcount = 0;
117 if (m_mode == read && m_flushable)
118 m_buffer_pos = m_buffer_end;
119 else
120 m_buffer_pos = m_buffer_start;
121 }
122
123 bool wxStreamBuffer::FillBuffer()
124 {
125 size_t count;
126
127 count = m_stream->OnSysRead(m_buffer_start, m_buffer_size);
128 m_buffer_end = m_buffer_start+count;
129 m_buffer_pos = m_buffer_start;
130
131 if (count == 0)
132 return FALSE;
133 return TRUE;
134 }
135
136 bool wxStreamBuffer::FlushBuffer()
137 {
138 size_t count, current;
139
140 if (m_buffer_pos == m_buffer_start || !m_flushable)
141 return FALSE;
142
143 current = m_buffer_pos-m_buffer_start;
144 count = m_stream->OnSysWrite(m_buffer_start, current);
145 if (count != current)
146 return FALSE;
147 m_buffer_pos = m_buffer_start;
148
149 return TRUE;
150 }
151
152 void wxStreamBuffer::GetFromBuffer(void *buffer, size_t size)
153 {
154 size_t s_toget = m_buffer_end-m_buffer_pos;
155
156 if (size < s_toget)
157 s_toget = size;
158
159 memcpy(buffer, m_buffer_pos, s_toget);
160 m_buffer_pos += s_toget;
161 }
162
163 void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size)
164 {
165 size_t s_toput = m_buffer_end-m_buffer_pos;
166
167 if (s_toput < size && !m_fixed) {
168 if (!m_buffer_start)
169 SetBufferIO(size);
170 else {
171 size_t delta = m_buffer_pos-m_buffer_start;
172
173 m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size);
174 m_buffer_pos = m_buffer_start + delta;
175 // I round a bit
176 m_buffer_size += size;
177 m_buffer_end = m_buffer_start+m_buffer_size;
178 }
179 s_toput = size;
180 }
181 if (s_toput > size)
182 s_toput = size;
183 memcpy(m_buffer_pos, buffer, s_toput);
184 m_buffer_pos += s_toput;
185 }
186
187 void wxStreamBuffer::PutChar(char c)
188 {
189 wxASSERT(m_stream != NULL);
190
191 if (!m_buffer_size) {
192 m_stream->OnSysWrite(&c, 1);
193 return;
194 }
195
196 if (GetDataLeft() == 0 && !FlushBuffer()) {
197 CHECK_ERROR(wxStream_WRITE_ERR);
198 return;
199 }
200
201 PutToBuffer(&c, 1);
202 m_stream->m_lastcount = 1;
203 }
204
205 char wxStreamBuffer::Peek()
206 {
207 char c;
208
209 wxASSERT(m_stream != NULL && m_buffer_size != 0);
210
211 if (!GetDataLeft()) {
212 CHECK_ERROR(wxStream_READ_ERR);
213 return 0;
214 }
215
216 GetFromBuffer(&c, 1);
217 m_buffer_pos--;
218
219 return c;
220 }
221
222 char wxStreamBuffer::GetChar()
223 {
224 char c;
225
226 wxASSERT(m_stream != NULL);
227
228 if (!m_buffer_size) {
229 m_stream->OnSysRead(&c, 1);
230 return c;
231 }
232
233 if (!GetDataLeft()) {
234 CHECK_ERROR(wxStream_READ_ERR);
235 return 0;
236 }
237
238 GetFromBuffer(&c, 1);
239
240 m_stream->m_lastcount = 1;
241 return c;
242 }
243
244 size_t wxStreamBuffer::Read(void *buffer, size_t size)
245 {
246 wxASSERT(m_stream != NULL);
247
248 if (m_mode == write)
249 return 0;
250
251 // ------------------
252 // Buffering disabled
253 // ------------------
254
255 m_stream->m_lasterror = wxStream_NOERROR;
256 if (!m_buffer_size)
257 return (m_stream->m_lastcount += m_stream->OnSysRead(buffer, size));
258
259 // -----------------
260 // Buffering enabled
261 // -----------------
262 size_t buf_left, orig_size = size;
263
264 while (size > 0) {
265 buf_left = GetDataLeft();
266
267 // First case: the requested buffer is larger than the stream buffer,
268 // we split it.
269 if (size > buf_left) {
270 GetFromBuffer(buffer, buf_left);
271 size -= buf_left;
272 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
273
274 if (!FillBuffer()) {
275 CHECK_ERROR(wxStream_EOF);
276 return (m_stream->m_lastcount = orig_size-size);
277 }
278 } else {
279
280 // Second case: we just copy from the stream buffer.
281 GetFromBuffer(buffer, size);
282 break;
283 }
284 }
285 return (m_stream->m_lastcount += orig_size);
286 }
287
288 size_t wxStreamBuffer::Read(wxStreamBuffer *s_buf)
289 {
290 char buf[BUF_TEMP_SIZE];
291 size_t s = 0, bytes_read = BUF_TEMP_SIZE;
292
293 if (m_mode == write)
294 return 0;
295
296 while (bytes_read != 0) {
297 bytes_read = Read(buf, bytes_read);
298 bytes_read = s_buf->Write(buf, bytes_read);
299 s += bytes_read;
300 }
301 return s;
302 }
303
304 size_t wxStreamBuffer::Write(const void *buffer, size_t size)
305 {
306 wxASSERT(m_stream != NULL);
307
308 if (m_mode == read)
309 return 0;
310
311 // ------------------
312 // Buffering disabled
313 // ------------------
314
315 m_stream->m_lasterror = wxStream_NOERROR;
316 if (!m_buffer_size && m_fixed)
317 return (m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size));
318
319 // ------------------
320 // Buffering enabled
321 // ------------------
322
323 size_t buf_left, orig_size = size;
324
325 while (size > 0) {
326 buf_left = m_buffer_end - m_buffer_pos;
327
328 // First case: the buffer to write is larger than the stream buffer,
329 // we split it
330 // NB: If stream buffer isn't fixed (as for wxMemoryOutputStream),
331 // we always go to the second case.
332 if (size > buf_left && m_fixed) {
333 PutToBuffer(buffer, buf_left);
334 size -= buf_left;
335 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
336
337 if (!FlushBuffer()) {
338 CHECK_ERROR(wxStream_WRITE_ERR);
339 return (m_stream->m_lastcount = orig_size-size);
340 }
341
342 m_buffer_pos = m_buffer_start;
343
344 } else {
345
346 // Second case: just copy it in the stream buffer.
347 PutToBuffer(buffer, size);
348 break;
349 }
350 }
351 return (m_stream->m_lastcount = orig_size);
352 }
353
354 size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
355 {
356 char buf[BUF_TEMP_SIZE];
357 size_t s = 0, bytes_count = BUF_TEMP_SIZE, b_count2;
358 wxInputStream *in_stream;
359
360 if (m_mode == read)
361 return 0;
362
363 in_stream = (wxInputStream *)sbuf->Stream();
364
365 while (bytes_count == BUF_TEMP_SIZE) {
366 b_count2 = sbuf->Read(buf, bytes_count);
367 bytes_count = Write(buf, b_count2);
368 if (b_count2 > bytes_count)
369 in_stream->Ungetch(buf+bytes_count, b_count2-bytes_count);
370 s += bytes_count;
371 }
372 return s;
373 }
374
375 off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
376 {
377 off_t ret_off, diff, last_access;
378
379 last_access = GetLastAccess();
380
381 if (!m_flushable) {
382 switch (mode) {
383 case wxFromStart: diff = pos; break;
384 case wxFromCurrent: diff = pos + GetIntPosition(); break;
385 case wxFromEnd: diff = pos + last_access; break;
386 default: return wxInvalidOffset;
387 }
388 if (diff < 0 || diff > last_access)
389 return wxInvalidOffset;
390 SetIntPosition(diff);
391 return diff;
392 }
393
394 switch (mode) {
395 case wxFromStart: {
396 // We'll try to compute an internal position later ...
397 ret_off = m_stream->OnSysSeek(pos, wxFromStart);
398 ResetBuffer();
399 return ret_off;
400 }
401 case wxFromCurrent: {
402 diff = pos + GetIntPosition();
403
404 if ( (diff > last_access) || (diff < 0) ) {
405 // We must take into account the fact that we have read something
406 // previously.
407 ret_off = m_stream->OnSysSeek(diff-last_access, wxFromCurrent);
408 ResetBuffer();
409 return ret_off;
410 } else {
411 SetIntPosition(diff);
412 return pos;
413 }
414 }
415 case wxFromEnd:
416 // Hard to compute: always seek to the requested position.
417 ret_off = m_stream->OnSysSeek(pos, wxFromEnd);
418 ResetBuffer();
419 return ret_off;
420 }
421 return wxInvalidOffset;
422 }
423
424 off_t wxStreamBuffer::Tell() const
425 {
426 off_t pos = m_stream->OnSysTell();
427 if (pos == wxInvalidOffset)
428 return wxInvalidOffset;
429
430 pos += GetIntPosition();
431
432 if (m_mode == read && m_flushable)
433 pos -= GetLastAccess();
434
435 return pos;
436 }
437
438 size_t wxStreamBuffer::GetDataLeft()
439 {
440 /* Why is this done? RR. */
441 if (m_buffer_end == m_buffer_pos && m_flushable)
442 FillBuffer();
443
444 return m_buffer_end-m_buffer_pos;
445 }
446
447 // ----------------------------------------------------------------------------
448 // wxStreamBase
449 // ----------------------------------------------------------------------------
450
451 wxStreamBase::wxStreamBase()
452 {
453 m_lasterror = wxStream_NOERROR;
454 m_lastcount = 0;
455 }
456
457 wxStreamBase::~wxStreamBase()
458 {
459 }
460
461 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer), size_t WXUNUSED(size))
462 {
463 return 0;
464 }
465
466 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer), size_t WXUNUSED(bufsize))
467 {
468 return 0;
469 }
470
471 off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode))
472 {
473 return wxInvalidOffset;
474 }
475
476 off_t wxStreamBase::OnSysTell() const
477 {
478 return wxInvalidOffset;
479 }
480
481 // ----------------------------------------------------------------------------
482 // wxInputStream
483 // ----------------------------------------------------------------------------
484
485 wxInputStream::wxInputStream()
486 : wxStreamBase(),
487 m_wback(NULL), m_wbacksize(0), m_wbackcur(0)
488 {
489 }
490
491 wxInputStream::~wxInputStream()
492 {
493 if (m_wback)
494 free(m_wback);
495 }
496
497 char *wxInputStream::AllocSpaceWBack(size_t needed_size)
498 {
499 /* get number of bytes left from previous wback buffer */
500 size_t toget = m_wbacksize - m_wbackcur;
501
502 /* allocate a buffer large enough to hold prev + new data */
503 char *temp_b = (char *) malloc(needed_size + toget);
504
505 if (!temp_b)
506 return NULL;
507
508 /* copy previous data (and free old buffer) if needed */
509 if (m_wback)
510 {
511 memmove(temp_b + needed_size, m_wback + m_wbackcur, toget);
512 free(m_wback);
513 }
514
515 /* done */
516 m_wback = temp_b;
517 m_wbackcur = 0;
518 m_wbacksize = needed_size + toget;
519
520 return (char *) m_wback;
521 }
522
523 size_t wxInputStream::GetWBack(char *buf, size_t bsize)
524 {
525 size_t s_toget = m_wbacksize-m_wbackcur;
526
527 if (!m_wback)
528 return 0;
529
530 if (bsize < s_toget)
531 s_toget = bsize;
532
533 memcpy(buf, (m_wback+m_wbackcur), s_toget);
534
535 m_wbackcur += s_toget;
536 if (m_wbackcur == m_wbacksize)
537 {
538 free(m_wback);
539 m_wback = (char *)NULL;
540 m_wbacksize = 0;
541 m_wbackcur = 0;
542 }
543
544 return s_toget;
545 }
546
547 size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
548 {
549 char *ptrback = AllocSpaceWBack(bufsize);
550 if (!ptrback)
551 return 0;
552
553 memcpy(ptrback, buf, bufsize);
554 return bufsize;
555 }
556
557 bool wxInputStream::Ungetch(char c)
558 {
559 char * ptrback = AllocSpaceWBack(1);
560 if (!ptrback)
561 return FALSE;
562
563 *ptrback = c;
564 return TRUE;
565 }
566
567 char wxInputStream::GetC()
568 {
569 char c;
570 Read(&c, 1);
571 return c;
572 }
573
574 wxInputStream& wxInputStream::Read(void *buffer, size_t size)
575 {
576 char *buf = (char *)buffer;
577
578 size_t retsize = GetWBack(buf, size);
579 if (retsize == size)
580 {
581 m_lastcount = size;
582 m_lasterror = wxStream_NOERROR;
583 return *this;
584 }
585 size -= retsize;
586 buf += retsize;
587
588 m_lastcount = OnSysRead(buf, size) + retsize;
589 return *this;
590 }
591
592 char wxInputStream::Peek()
593 {
594 char c;
595 Read(&c, 1);
596 if (m_lasterror == wxStream_NOERROR)
597 {
598 Ungetch(c);
599 return c;
600 }
601
602 return 0;
603 }
604
605 wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
606 {
607 char buf[BUF_TEMP_SIZE];
608 size_t bytes_read = BUF_TEMP_SIZE;
609
610 while (bytes_read == BUF_TEMP_SIZE)
611 {
612 bytes_read = Read(buf, bytes_read).LastRead();
613 bytes_read = stream_out.Write(buf, bytes_read).LastWrite();
614 }
615 return *this;
616 }
617
618 off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
619 {
620 /* Should be check and improve, just to remove a slight bug !
621 I don't know whether it should be put as well in wxFileInputStream::OnSysSeek ? */
622 if (m_lasterror==wxSTREAM_EOF)
623 m_lasterror=wxSTREAM_NOERROR;
624
625 /* A call to SeekI() will automatically invalidate any previous call
626 to Ungetch(), otherwise it would be possible to SeekI() to one
627 one position, unread some bytes there, SeekI() to another position
628 and the data would be corrupted.
629
630 GRG: Could add code here to try to navigate within the wback
631 buffer if possible, but is it really needed? It would only work
632 when seeking in wxFromCurrent mode, else it would invalidate
633 anyway...
634 */
635 if (m_wback)
636 {
637 free(m_wback);
638 m_wback = (char*) NULL;
639 m_wbacksize = 0;
640 m_wbackcur = 0;
641 }
642
643 return OnSysSeek(pos, mode);
644 }
645
646 off_t wxInputStream::TellI() const
647 {
648 /* GRG: Changed to make it compatible with the wback buffer */
649 off_t pos = OnSysTell();
650
651 if (pos != wxInvalidOffset)
652 pos -= (m_wbacksize - m_wbackcur);
653
654 return pos;
655 }
656
657 // --------------------
658 // Overloaded operators
659 // --------------------
660
661 #if wxUSE_SERIAL
662 wxInputStream& wxInputStream::operator>>(wxObject *& obj)
663 {
664 wxObjectInputStream obj_s(*this);
665 obj = obj_s.LoadObject();
666 return *this;
667 }
668 #endif
669
670
671 // ----------------------------------------------------------------------------
672 // wxOutputStream
673 // ----------------------------------------------------------------------------
674 wxOutputStream::wxOutputStream()
675 : wxStreamBase()
676 {
677 }
678
679 wxOutputStream::~wxOutputStream()
680 {
681 }
682
683 void wxOutputStream::PutC(char c)
684 {
685 Write((void *) &c, 1);
686 }
687
688 wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
689 {
690 m_lastcount = OnSysWrite(buffer, size);
691 return *this;
692 }
693
694 wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
695 {
696 stream_in.Read(*this);
697 return *this;
698 }
699
700 off_t wxOutputStream::TellO() const
701 {
702 return OnSysTell();
703 }
704
705 off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
706 {
707 return OnSysSeek(pos, mode);
708 }
709
710 void wxOutputStream::Sync()
711 {
712 }
713
714 #if wxUSE_SERIAL
715 wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
716 {
717 wxObjectOutputStream obj_s(*this);
718 obj_s.SaveObject(obj);
719 return *this;
720 }
721 #endif
722
723 // ----------------------------------------------------------------------------
724 // wxCountingOutputStream
725 // ----------------------------------------------------------------------------
726
727 wxCountingOutputStream::wxCountingOutputStream ()
728 : wxOutputStream()
729 {
730 m_currentPos = 0;
731 }
732
733 size_t wxCountingOutputStream::GetSize() const
734 {
735 return m_lastcount;
736 }
737
738 size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size)
739 {
740 m_currentPos += size;
741 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
742 return m_currentPos;
743 }
744
745 off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
746 {
747 if (mode == wxFromStart)
748 m_currentPos = pos;
749 if (mode == wxFromEnd)
750 m_currentPos = m_lastcount + pos;
751 else
752 m_currentPos += pos;
753
754 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
755
756 return m_currentPos;
757 }
758
759 off_t wxCountingOutputStream::OnSysTell() const
760 {
761 return m_currentPos;
762 }
763
764 // ----------------------------------------------------------------------------
765 // wxFilterInputStream
766 // ----------------------------------------------------------------------------
767
768 wxFilterInputStream::wxFilterInputStream()
769 : wxInputStream()
770 {
771 }
772
773 wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
774 : wxInputStream()
775 {
776 m_parent_i_stream = &stream;
777 }
778
779 wxFilterInputStream::~wxFilterInputStream()
780 {
781 }
782
783 // ----------------------------------------------------------------------------
784 // wxFilterOutputStream
785 // ----------------------------------------------------------------------------
786 wxFilterOutputStream::wxFilterOutputStream()
787 : wxOutputStream()
788 {
789 }
790
791 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
792 : wxOutputStream()
793 {
794 m_parent_o_stream = &stream;
795 }
796
797 wxFilterOutputStream::~wxFilterOutputStream()
798 {
799 }
800
801 // ----------------------------------------------------------------------------
802 // wxBufferedInputStream
803 // ----------------------------------------------------------------------------
804 wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s)
805 : wxFilterInputStream(s)
806 {
807 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
808 m_i_streambuf->SetBufferIO(1024);
809 }
810
811 wxBufferedInputStream::~wxBufferedInputStream()
812 {
813 off_t unused_bytes=m_i_streambuf->GetBufferPos()-m_i_streambuf->GetBufferEnd();
814 m_parent_i_stream->SeekI(unused_bytes,wxFromCurrent);
815
816 delete m_i_streambuf;
817 }
818
819 char wxBufferedInputStream::Peek()
820 {
821 return m_i_streambuf->Peek();
822 }
823
824 wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size)
825 {
826 size_t retsize;
827 char *buf = (char *)buffer;
828
829 retsize = GetWBack(buf, size);
830 m_lastcount = retsize;
831 if (retsize == size)
832 {
833 m_lasterror = wxStream_NOERROR;
834 return *this;
835 }
836 size -= retsize;
837 buf += retsize;
838
839 m_i_streambuf->Read(buf, size);
840
841 return *this;
842 }
843
844 off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
845 {
846 return m_i_streambuf->Seek(pos, mode);
847 }
848
849 off_t wxBufferedInputStream::TellI() const
850 {
851 return m_i_streambuf->Tell();
852 }
853
854 size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
855 {
856 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
857 }
858
859 off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
860 {
861 return m_parent_i_stream->SeekI(seek, mode);
862 }
863
864 off_t wxBufferedInputStream::OnSysTell() const
865 {
866 return m_parent_i_stream->TellI();
867 }
868
869
870 // ----------------------------------------------------------------------------
871 // wxBufferedOutputStream
872 // ----------------------------------------------------------------------------
873
874 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s)
875 : wxFilterOutputStream(s)
876 {
877 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
878 m_o_streambuf->SetBufferIO(1024);
879 }
880
881 wxBufferedOutputStream::~wxBufferedOutputStream()
882 {
883 Sync();
884 delete m_o_streambuf;
885 }
886
887 wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
888 {
889 m_lastcount = 0;
890 m_o_streambuf->Write(buffer, size);
891 return *this;
892 }
893
894 off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
895 {
896 Sync();
897 return m_o_streambuf->Seek(pos, mode);
898 }
899
900 off_t wxBufferedOutputStream::TellO() const
901 {
902 return m_o_streambuf->Tell();
903 }
904
905 void wxBufferedOutputStream::Sync()
906 {
907 m_o_streambuf->FlushBuffer();
908 m_parent_o_stream->Sync();
909 }
910
911 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
912 {
913 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
914 }
915
916 off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
917 {
918 return m_parent_o_stream->SeekO(seek, mode);
919 }
920
921 off_t wxBufferedOutputStream::OnSysTell() const
922 {
923 return m_parent_o_stream->TellO();
924 }
925
926 size_t wxBufferedOutputStream::GetSize() const
927 {
928 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
929 }
930
931 // ----------------------------------------------------------------------------
932 // Some IOManip function
933 // ----------------------------------------------------------------------------
934
935 wxOutputStream& wxEndL(wxOutputStream& stream)
936 {
937 #ifdef __MSW__
938 return stream.Write("\r\n", 2);
939 #else
940 #ifdef __WXMAC__
941 return stream.Write("\r", 1);
942 #else
943 return stream.Write("\n", 1);
944 #endif
945 #endif
946 }
947
948 #endif
949 // wxUSE_STREAMS