]> git.saurik.com Git - wxWidgets.git/blame - src/common/stream.cpp
1. fixed (?) blitting bitmaps with mask
[wxWidgets.git] / src / common / stream.cpp
CommitLineData
3d4c6a21
GL
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
db138a4c
JS
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
ce4169a4
RR
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
6d44bf31 29#include <ctype.h>
3096bd2f
VZ
30#include "wx/stream.h"
31#include "wx/datstrm.h"
32#include "wx/objstrm.h"
db138a4c 33
8ef6a930
GL
34#define BUF_TEMP_SIZE 10000
35
6d44bf31
GL
36// ----------------------------------------------------------------------------
37// wxStreamBuffer
38// ----------------------------------------------------------------------------
39
926c550d
GL
40#define CHECK_ERROR(err) \
41 if (m_stream->m_lasterror == wxStream_NOERROR) \
42 m_stream->m_lasterror = err
43
75ed1d15 44wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
6d44bf31 45 : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
fae05df5 46 m_buffer_size(0), m_fixed(TRUE), m_flushable(TRUE), m_stream(&stream),
8ef6a930 47 m_mode(mode), m_destroybuf(FALSE), m_destroystream(FALSE)
6d44bf31
GL
48{
49}
50
84b46c35
GL
51wxStreamBuffer::wxStreamBuffer(BufMode mode)
52 : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
fae05df5 53 m_buffer_size(0), m_fixed(TRUE), m_flushable(FALSE), m_stream(NULL),
8ef6a930 54 m_mode(mode), m_destroybuf(FALSE), m_destroystream(TRUE)
84b46c35 55{
8ef6a930 56 m_stream = new wxStreamBase();
84b46c35
GL
57}
58
59wxStreamBuffer::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;
8ef6a930 70 m_destroystream = FALSE;
84b46c35
GL
71}
72
75ed1d15 73wxStreamBuffer::~wxStreamBuffer()
6d44bf31 74{
84b46c35
GL
75 if (m_destroybuf)
76 wxDELETEA(m_buffer_start);
8ef6a930
GL
77 if (m_destroystream)
78 delete m_stream;
6d44bf31
GL
79}
80
6d44bf31
GL
81void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end)
82{
84b46c35
GL
83 if (m_destroybuf)
84 wxDELETEA(m_buffer_start);
885ee235
GL
85 m_buffer_start = buffer_start;
86 m_buffer_end = buffer_end;
6d44bf31
GL
87
88 m_buffer_size = m_buffer_end-m_buffer_start;
84b46c35 89 m_destroybuf = FALSE;
75ed1d15 90 ResetBuffer();
6d44bf31
GL
91}
92
93void wxStreamBuffer::SetBufferIO(size_t bufsize)
94{
885ee235
GL
95 char *b_start;
96
926c550d
GL
97 if (m_destroybuf)
98 wxDELETEA(m_buffer_start);
6d44bf31
GL
99
100 if (!bufsize) {
d984207c
RR
101 m_buffer_start = (char*)NULL;
102 m_buffer_end = (char*)NULL;
103 m_buffer_pos = (char*)NULL;
6d44bf31 104 m_buffer_size = 0;
885ee235 105 return;
6d44bf31
GL
106 }
107
885ee235 108 b_start = new char[bufsize];
885ee235 109 SetBufferIO(b_start, b_start + bufsize);
84b46c35 110 m_destroybuf = TRUE;
6d44bf31
GL
111}
112
113void wxStreamBuffer::ResetBuffer()
114{
2a040d3f 115 m_stream->m_lasterror = wxStream_NOERROR;
07b73270 116 m_stream->m_lastcount = 0;
1cb6da2d 117 if (m_mode == read && m_flushable)
6d44bf31
GL
118 m_buffer_pos = m_buffer_end;
119 else
120 m_buffer_pos = m_buffer_start;
121}
122
75ed1d15
GL
123bool 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
136bool wxStreamBuffer::FlushBuffer()
137{
138 size_t count, current;
139
84b46c35 140 if (m_buffer_pos == m_buffer_start || !m_flushable)
75ed1d15
GL
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
152void 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
163void 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) {
56dc1ffd
GL
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 }
75ed1d15
GL
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
84b46c35
GL
187void 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
9fc0fe37
GL
196 if (GetDataLeft() == 0 && !FlushBuffer()) {
197 CHECK_ERROR(wxStream_WRITE_ERR);
84b46c35 198 return;
8ef6a930 199 }
84b46c35
GL
200
201 PutToBuffer(&c, 1);
202 m_stream->m_lastcount = 1;
203}
204
6319afe3
GL
205char 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
84b46c35
GL
222char 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
8ef6a930 233 if (!GetDataLeft()) {
926c550d 234 CHECK_ERROR(wxStream_READ_ERR);
84b46c35 235 return 0;
8ef6a930 236 }
84b46c35
GL
237
238 GetFromBuffer(&c, 1);
e57e26dd 239
84b46c35
GL
240 m_stream->m_lastcount = 1;
241 return c;
242}
243
8ef6a930 244size_t wxStreamBuffer::Read(void *buffer, size_t size)
6d44bf31 245{
75ed1d15 246 wxASSERT(m_stream != NULL);
6d44bf31 247
7f42cff1
GL
248 if (m_mode == write)
249 return 0;
250
6d44bf31
GL
251 // ------------------
252 // Buffering disabled
253 // ------------------
254
2a040d3f 255 m_stream->m_lasterror = wxStream_NOERROR;
926c550d 256 if (!m_buffer_size)
8ef6a930 257 return (m_stream->m_lastcount += m_stream->OnSysRead(buffer, size));
6d44bf31
GL
258
259 // -----------------
260 // Buffering enabled
261 // -----------------
262 size_t buf_left, orig_size = size;
6d44bf31
GL
263
264 while (size > 0) {
75ed1d15 265 buf_left = GetDataLeft();
6d44bf31
GL
266
267 // First case: the requested buffer is larger than the stream buffer,
84b46c35 268 // we split it.
6d44bf31 269 if (size > buf_left) {
75ed1d15
GL
270 GetFromBuffer(buffer, buf_left);
271 size -= buf_left;
6d44bf31
GL
272 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
273
75ed1d15 274 if (!FillBuffer()) {
6319afe3 275 CHECK_ERROR(wxStream_EOF);
8ef6a930 276 return (m_stream->m_lastcount = orig_size-size);
6d44bf31
GL
277 }
278 } else {
279
280 // Second case: we just copy from the stream buffer.
75ed1d15 281 GetFromBuffer(buffer, size);
6d44bf31
GL
282 break;
283 }
284 }
8ef6a930 285 return (m_stream->m_lastcount += orig_size);
6d44bf31
GL
286}
287
8ef6a930
GL
288size_t wxStreamBuffer::Read(wxStreamBuffer *s_buf)
289{
290 char buf[BUF_TEMP_SIZE];
291 size_t s = 0, bytes_read = BUF_TEMP_SIZE;
292
7f42cff1
GL
293 if (m_mode == write)
294 return 0;
295
062c4861 296 while (bytes_read != 0) {
8ef6a930
GL
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
304size_t wxStreamBuffer::Write(const void *buffer, size_t size)
6d44bf31 305{
75ed1d15 306 wxASSERT(m_stream != NULL);
6d44bf31 307
7f42cff1
GL
308 if (m_mode == read)
309 return 0;
310
6d44bf31
GL
311 // ------------------
312 // Buffering disabled
313 // ------------------
314
2a040d3f 315 m_stream->m_lasterror = wxStream_NOERROR;
56dc1ffd 316 if (!m_buffer_size && m_fixed)
8ef6a930 317 return (m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size));
6d44bf31
GL
318
319 // ------------------
320 // Buffering enabled
321 // ------------------
322
323 size_t buf_left, orig_size = size;
6d44bf31
GL
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
56dc1ffd
GL
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) {
75ed1d15 333 PutToBuffer(buffer, buf_left);
6d44bf31
GL
334 size -= buf_left;
335 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
336
75ed1d15 337 if (!FlushBuffer()) {
926c550d 338 CHECK_ERROR(wxStream_WRITE_ERR);
8ef6a930 339 return (m_stream->m_lastcount = orig_size-size);
6d44bf31 340 }
8ef6a930 341
6d44bf31
GL
342 m_buffer_pos = m_buffer_start;
343
344 } else {
345
346 // Second case: just copy it in the stream buffer.
75ed1d15 347 PutToBuffer(buffer, size);
6d44bf31
GL
348 break;
349 }
350 }
8ef6a930
GL
351 return (m_stream->m_lastcount = orig_size);
352}
353
354size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
355{
356 char buf[BUF_TEMP_SIZE];
eb4e516d 357 size_t s = 0, bytes_count = BUF_TEMP_SIZE, b_count2;
fae05df5 358 wxInputStream *in_stream;
8ef6a930 359
7f42cff1
GL
360 if (m_mode == read)
361 return 0;
362
fae05df5
GL
363 in_stream = (wxInputStream *)sbuf->Stream();
364
8ef6a930 365 while (bytes_count == BUF_TEMP_SIZE) {
eb4e516d
GL
366 b_count2 = sbuf->Read(buf, bytes_count);
367 bytes_count = Write(buf, b_count2);
368 if (b_count2 > bytes_count)
fae05df5 369 in_stream->Ungetch(buf+bytes_count, b_count2-bytes_count);
8ef6a930
GL
370 s += bytes_count;
371 }
372 return s;
75ed1d15
GL
373}
374
375off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
376{
377 off_t ret_off, diff, last_access;
378
379 last_access = GetLastAccess();
380
8ef6a930 381 if (!m_flushable) {
d984207c
RR
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 }
84b46c35
GL
388 if (diff < 0 || diff > last_access)
389 return wxInvalidOffset;
390 SetIntPosition(diff);
391 return diff;
392 }
393
75ed1d15
GL
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) ) {
d4feedcf
GL
405 // We must take into account the fact that we have read something
406 // previously.
f1f5976f 407 ret_off = m_stream->OnSysSeek(diff-last_access, wxFromCurrent);
75ed1d15
GL
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
424off_t wxStreamBuffer::Tell() const
425{
c7a9fa36 426 off_t pos = m_stream->OnSysTell();
84b46c35 427 if (pos == wxInvalidOffset)
c7a9fa36
RR
428 return wxInvalidOffset;
429
430 pos += GetIntPosition();
431
432 if (m_mode == read && m_flushable)
433 pos -= GetLastAccess();
434
435 return pos;
75ed1d15
GL
436}
437
8ef6a930 438size_t wxStreamBuffer::GetDataLeft()
75ed1d15 439{
c7a9fa36
RR
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;
75ed1d15
GL
445}
446
447// ----------------------------------------------------------------------------
448// wxStreamBase
449// ----------------------------------------------------------------------------
450
451wxStreamBase::wxStreamBase()
452{
c7a9fa36
RR
453 m_lasterror = wxStream_NOERROR;
454 m_lastcount = 0;
75ed1d15
GL
455}
456
457wxStreamBase::~wxStreamBase()
458{
459}
460
df875e59 461size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer), size_t WXUNUSED(size))
75ed1d15 462{
c7a9fa36 463 return 0;
75ed1d15
GL
464}
465
df875e59 466size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer), size_t WXUNUSED(bufsize))
75ed1d15 467{
c7a9fa36 468 return 0;
75ed1d15
GL
469}
470
df875e59 471off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode))
75ed1d15 472{
c7a9fa36 473 return wxInvalidOffset;
75ed1d15
GL
474}
475
84b46c35 476off_t wxStreamBase::OnSysTell() const
75ed1d15 477{
c7a9fa36 478 return wxInvalidOffset;
6d44bf31
GL
479}
480
1678ad78
GL
481// ----------------------------------------------------------------------------
482// wxInputStream
483// ----------------------------------------------------------------------------
484
3d4c6a21 485wxInputStream::wxInputStream()
fae05df5
GL
486 : wxStreamBase(),
487 m_wback(NULL), m_wbacksize(0), m_wbackcur(0)
3d4c6a21 488{
6d44bf31
GL
489}
490
fae05df5 491wxInputStream::~wxInputStream()
6d44bf31 492{
fae05df5
GL
493 if (m_wback)
494 free(m_wback);
3d4c6a21
GL
495}
496
fae05df5 497char *wxInputStream::AllocSpaceWBack(size_t needed_size)
3d4c6a21 498{
c7a9fa36
RR
499 /* get number of bytes left from previous wback buffer */
500 size_t toget = m_wbacksize - m_wbackcur;
fae05df5 501
c7a9fa36
RR
502 /* allocate a buffer large enough to hold prev + new data */
503 char *temp_b = (char *) malloc(needed_size + toget);
fae05df5 504
c7a9fa36
RR
505 if (!temp_b)
506 return NULL;
fae05df5 507
c7a9fa36
RR
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 }
5ac8158a 514
c7a9fa36
RR
515 /* done */
516 m_wback = temp_b;
517 m_wbackcur = 0;
518 m_wbacksize = needed_size + toget;
783ff666 519
c7a9fa36 520 return (char *) m_wback;
6d44bf31
GL
521}
522
fae05df5 523size_t wxInputStream::GetWBack(char *buf, size_t bsize)
6d44bf31 524{
c7a9fa36 525 size_t s_toget = m_wbacksize-m_wbackcur;
fae05df5 526
c7a9fa36
RR
527 if (!m_wback)
528 return 0;
a324a7bc 529
c7a9fa36
RR
530 if (bsize < s_toget)
531 s_toget = bsize;
fae05df5 532
c7a9fa36 533 memcpy(buf, (m_wback+m_wbackcur), s_toget);
fae05df5 534
c7a9fa36
RR
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 }
fae05df5 543
c7a9fa36 544 return s_toget;
6d44bf31
GL
545}
546
8f7173ab 547size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
fae05df5 548{
c7a9fa36
RR
549 char *ptrback = AllocSpaceWBack(bufsize);
550 if (!ptrback)
551 return 0;
552
553 memcpy(ptrback, buf, bufsize);
554 return bufsize;
fae05df5
GL
555}
556
557bool wxInputStream::Ungetch(char c)
1e3eca9d 558{
c7a9fa36
RR
559 char * ptrback = AllocSpaceWBack(1);
560 if (!ptrback)
561 return FALSE;
1e3eca9d 562
c7a9fa36
RR
563 *ptrback = c;
564 return TRUE;
fae05df5
GL
565}
566
567char wxInputStream::GetC()
568{
c7a9fa36
RR
569 char c;
570 Read(&c, 1);
571 return c;
1e3eca9d
GL
572}
573
6d44bf31
GL
574wxInputStream& wxInputStream::Read(void *buffer, size_t size)
575{
c7a9fa36 576 char *buf = (char *)buffer;
fae05df5 577
c7a9fa36
RR
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;
fae05df5 587
c7a9fa36
RR
588 m_lastcount = OnSysRead(buf, size) + retsize;
589 return *this;
3d4c6a21
GL
590}
591
75ed1d15
GL
592char wxInputStream::Peek()
593{
c7a9fa36
RR
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;
75ed1d15
GL
603}
604
3d4c6a21
GL
605wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
606{
c7a9fa36
RR
607 char buf[BUF_TEMP_SIZE];
608 size_t bytes_read = BUF_TEMP_SIZE;
3d4c6a21 609
c7a9fa36
RR
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;
3d4c6a21
GL
616}
617
75ed1d15
GL
618off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
619{
c7a9fa36
RR
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 if (m_wback)
630 {
631 free(m_wback);
632 m_wback = (char*) NULL;
633 m_wbacksize = 0;
634 m_wbackcur = 0;
635 }
fe8aa971 636
c7a9fa36 637 return OnSysSeek(pos, mode);
75ed1d15
GL
638}
639
640off_t wxInputStream::TellI() const
641{
c7a9fa36 642 return OnSysTell();
75ed1d15
GL
643}
644
645// --------------------
646// Overloaded operators
647// --------------------
648
fae05df5
GL
649#if wxUSE_SERIAL
650wxInputStream& wxInputStream::operator>>(wxObject *& obj)
1678ad78 651{
c7a9fa36
RR
652 wxObjectInputStream obj_s(*this);
653 obj = obj_s.LoadObject();
654 return *this;
1678ad78 655}
fae05df5 656#endif
1678ad78 657
1678ad78 658
fae05df5
GL
659// ----------------------------------------------------------------------------
660// wxOutputStream
661// ----------------------------------------------------------------------------
662wxOutputStream::wxOutputStream()
663 : wxStreamBase()
1678ad78 664{
1678ad78
GL
665}
666
fae05df5 667wxOutputStream::~wxOutputStream()
123a7fdd 668{
123a7fdd
GL
669}
670
7513f9ff
GRG
671void wxOutputStream::PutC(char c)
672{
c7a9fa36 673 Write((void *) &c, 1);
7513f9ff
GRG
674}
675
fae05df5 676wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
1678ad78 677{
c7a9fa36
RR
678 m_lastcount = OnSysWrite(buffer, size);
679 return *this;
1678ad78
GL
680}
681
fae05df5 682wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
38830220 683{
c7a9fa36
RR
684 stream_in.Read(*this);
685 return *this;
38830220
RR
686}
687
fae05df5 688off_t wxOutputStream::TellO() const
38830220 689{
c7a9fa36 690 return OnSysTell();
38830220
RR
691}
692
fae05df5 693off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
38830220 694{
c7a9fa36 695 return OnSysSeek(pos, mode);
38830220
RR
696}
697
fae05df5 698void wxOutputStream::Sync()
1678ad78 699{
1678ad78
GL
700}
701
47d67540 702#if wxUSE_SERIAL
fae05df5 703wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
123a7fdd 704{
c7a9fa36
RR
705 wxObjectOutputStream obj_s(*this);
706 obj_s.SaveObject(obj);
707 return *this;
123a7fdd 708}
fcc6dddd 709#endif
123a7fdd 710
e2acb9ae
RR
711// ----------------------------------------------------------------------------
712// wxCountingOutputStream
713// ----------------------------------------------------------------------------
714
715wxCountingOutputStream::wxCountingOutputStream ()
716 : wxOutputStream()
717{
c7a9fa36 718 m_currentPos = 0;
e2acb9ae
RR
719}
720
721size_t wxCountingOutputStream::GetSize() const
722{
c7a9fa36 723 return m_lastcount;
e2acb9ae
RR
724}
725
5e0201ea 726size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size)
e2acb9ae 727{
c7a9fa36
RR
728 m_currentPos += size;
729 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
730 return m_currentPos;
e2acb9ae
RR
731}
732
733off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
734{
c7a9fa36
RR
735 if (mode == wxFromStart)
736 m_currentPos = pos;
737 if (mode == wxFromEnd)
738 m_currentPos = m_lastcount + pos;
739 else
740 m_currentPos += pos;
741
742 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
e2acb9ae 743
c7a9fa36 744 return m_currentPos;
e2acb9ae
RR
745}
746
747off_t wxCountingOutputStream::OnSysTell() const
748{
c7a9fa36 749 return m_currentPos;
e2acb9ae
RR
750}
751
1678ad78 752// ----------------------------------------------------------------------------
fae05df5 753// wxFilterInputStream
1678ad78 754// ----------------------------------------------------------------------------
e2acb9ae 755
fae05df5
GL
756wxFilterInputStream::wxFilterInputStream()
757 : wxInputStream()
3d4c6a21 758{
6d44bf31
GL
759}
760
fae05df5
GL
761wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
762 : wxInputStream()
6d44bf31 763{
c7a9fa36 764 m_parent_i_stream = &stream;
3d4c6a21
GL
765}
766
fae05df5 767wxFilterInputStream::~wxFilterInputStream()
3d4c6a21 768{
6d44bf31
GL
769}
770
fae05df5
GL
771// ----------------------------------------------------------------------------
772// wxFilterOutputStream
773// ----------------------------------------------------------------------------
774wxFilterOutputStream::wxFilterOutputStream()
775 : wxOutputStream()
6d44bf31 776{
3d4c6a21
GL
777}
778
fae05df5
GL
779wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
780 : wxOutputStream()
3d4c6a21 781{
c7a9fa36 782 m_parent_o_stream = &stream;
6d44bf31
GL
783}
784
fae05df5 785wxFilterOutputStream::~wxFilterOutputStream()
6d44bf31 786{
6d44bf31
GL
787}
788
fae05df5
GL
789// ----------------------------------------------------------------------------
790// wxBufferedInputStream
791// ----------------------------------------------------------------------------
792wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s)
793 : wxFilterInputStream(s)
6d44bf31 794{
c7a9fa36
RR
795 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
796 m_i_streambuf->SetBufferIO(1024);
6d44bf31
GL
797}
798
fae05df5 799wxBufferedInputStream::~wxBufferedInputStream()
6d44bf31 800{
c7a9fa36
RR
801 off_t unused_bytes=m_i_streambuf->GetBufferPos()-m_i_streambuf->GetBufferEnd();
802 m_parent_i_stream->SeekI(unused_bytes,wxFromCurrent);
672cedf8 803
c7a9fa36 804 delete m_i_streambuf;
6d44bf31
GL
805}
806
6319afe3
GL
807char wxBufferedInputStream::Peek()
808{
c7a9fa36 809 return m_i_streambuf->Peek();
6319afe3
GL
810}
811
fae05df5 812wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size)
1e3eca9d 813{
c7a9fa36
RR
814 size_t retsize;
815 char *buf = (char *)buffer;
1e3eca9d 816
c7a9fa36
RR
817 retsize = GetWBack(buf, size);
818 m_lastcount = retsize;
819 if (retsize == size)
820 {
821 m_lasterror = wxStream_NOERROR;
822 return *this;
823 }
824 size -= retsize;
825 buf += retsize;
1e3eca9d 826
c7a9fa36 827 m_i_streambuf->Read(buf, size);
6d44bf31 828
c7a9fa36 829 return *this;
6d44bf31
GL
830}
831
fae05df5 832off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
6d44bf31 833{
c7a9fa36 834 return m_i_streambuf->Seek(pos, mode);
6d44bf31
GL
835}
836
fae05df5 837off_t wxBufferedInputStream::TellI() const
6d44bf31 838{
c7a9fa36 839 return m_i_streambuf->Tell();
38830220 840}
6d44bf31 841
fae05df5 842size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
38830220 843{
c7a9fa36 844 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
38830220
RR
845}
846
fae05df5 847off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
38830220 848{
c7a9fa36 849 return m_parent_i_stream->SeekI(seek, mode);
6d44bf31
GL
850}
851
fae05df5 852off_t wxBufferedInputStream::OnSysTell() const
6d44bf31 853{
c7a9fa36 854 return m_parent_i_stream->TellI();
38830220 855}
6d44bf31 856
c7a9fa36 857
fae05df5
GL
858// ----------------------------------------------------------------------------
859// wxBufferedOutputStream
860// ----------------------------------------------------------------------------
6d44bf31 861
fae05df5
GL
862wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s)
863 : wxFilterOutputStream(s)
6d44bf31 864{
c7a9fa36
RR
865 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
866 m_o_streambuf->SetBufferIO(1024);
6d44bf31
GL
867}
868
fae05df5 869wxBufferedOutputStream::~wxBufferedOutputStream()
6d44bf31 870{
c7a9fa36
RR
871 Sync();
872 delete m_o_streambuf;
3d4c6a21
GL
873}
874
fae05df5 875wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
123a7fdd 876{
c7a9fa36
RR
877 m_lastcount = 0;
878 m_o_streambuf->Write(buffer, size);
879 return *this;
123a7fdd
GL
880}
881
fae05df5 882off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
f4ada568 883{
c7a9fa36
RR
884 Sync();
885 return m_o_streambuf->Seek(pos, mode);
f4ada568
GL
886}
887
fae05df5 888off_t wxBufferedOutputStream::TellO() const
3d4c6a21 889{
c7a9fa36 890 return m_o_streambuf->Tell();
3d4c6a21
GL
891}
892
fae05df5 893void wxBufferedOutputStream::Sync()
3d4c6a21 894{
c7a9fa36
RR
895 m_o_streambuf->FlushBuffer();
896 m_parent_o_stream->Sync();
3d4c6a21 897}
219f895a 898
fae05df5 899size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
f4ada568 900{
c7a9fa36 901 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
f4ada568
GL
902}
903
fae05df5 904off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
219f895a 905{
c7a9fa36 906 return m_parent_o_stream->SeekO(seek, mode);
219f895a
RR
907}
908
fae05df5 909off_t wxBufferedOutputStream::OnSysTell() const
219f895a 910{
c7a9fa36
RR
911 return m_parent_o_stream->TellO();
912}
913
914size_t wxBufferedOutputStream::GetSize() const
915{
916 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
219f895a 917}
6d44bf31 918
6d44bf31
GL
919// ----------------------------------------------------------------------------
920// Some IOManip function
921// ----------------------------------------------------------------------------
922
923wxOutputStream& wxEndL(wxOutputStream& stream)
924{
925#ifdef __MSW__
926 return stream.Write("\r\n", 2);
1e3eca9d
GL
927#else
928#ifdef __WXMAC__
929 return stream.Write("\r", 1);
6d44bf31
GL
930#else
931 return stream.Write("\n", 1);
932#endif
1e3eca9d 933#endif
6d44bf31 934}
ce4169a4
RR
935
936#endif
937 // wxUSE_STREAMS