]> git.saurik.com Git - wxWidgets.git/blame - src/common/stream.cpp
fix from Robert
[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);
cd6ce4a9 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) {
cd6ce4a9 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();
cd6ce4a9 431
c7a9fa36
RR
432 if (m_mode == read && m_flushable)
433 pos -= GetLastAccess();
cd6ce4a9 434
c7a9fa36 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();
cd6ce4a9 443
c7a9fa36 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
cd6ce4a9
VZ
497bool wxInputStream::Eof() const
498{
499 wxInputStream *self = (wxInputStream *)this; // const_cast
500
501 char c;
502 self->Read(&c, 1);
503 if ( GetLastError() == wxSTREAM_EOF )
504 {
505 return TRUE;
506 }
507
508 self->Ungetch(c);
509
510 return FALSE;
511}
512
fae05df5 513char *wxInputStream::AllocSpaceWBack(size_t needed_size)
3d4c6a21 514{
c7a9fa36
RR
515 /* get number of bytes left from previous wback buffer */
516 size_t toget = m_wbacksize - m_wbackcur;
fae05df5 517
c7a9fa36
RR
518 /* allocate a buffer large enough to hold prev + new data */
519 char *temp_b = (char *) malloc(needed_size + toget);
fae05df5 520
c7a9fa36
RR
521 if (!temp_b)
522 return NULL;
fae05df5 523
c7a9fa36
RR
524 /* copy previous data (and free old buffer) if needed */
525 if (m_wback)
526 {
527 memmove(temp_b + needed_size, m_wback + m_wbackcur, toget);
528 free(m_wback);
529 }
5ac8158a 530
c7a9fa36
RR
531 /* done */
532 m_wback = temp_b;
533 m_wbackcur = 0;
534 m_wbacksize = needed_size + toget;
783ff666 535
c7a9fa36 536 return (char *) m_wback;
6d44bf31
GL
537}
538
fae05df5 539size_t wxInputStream::GetWBack(char *buf, size_t bsize)
6d44bf31 540{
c7a9fa36 541 size_t s_toget = m_wbacksize-m_wbackcur;
fae05df5 542
c7a9fa36
RR
543 if (!m_wback)
544 return 0;
a324a7bc 545
c7a9fa36
RR
546 if (bsize < s_toget)
547 s_toget = bsize;
fae05df5 548
c7a9fa36 549 memcpy(buf, (m_wback+m_wbackcur), s_toget);
fae05df5 550
c7a9fa36 551 m_wbackcur += s_toget;
cd6ce4a9 552 if (m_wbackcur == m_wbacksize)
c7a9fa36
RR
553 {
554 free(m_wback);
555 m_wback = (char *)NULL;
556 m_wbacksize = 0;
557 m_wbackcur = 0;
558 }
cd6ce4a9 559
c7a9fa36 560 return s_toget;
6d44bf31
GL
561}
562
8f7173ab 563size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
fae05df5 564{
c7a9fa36
RR
565 char *ptrback = AllocSpaceWBack(bufsize);
566 if (!ptrback)
567 return 0;
cd6ce4a9 568
c7a9fa36
RR
569 memcpy(ptrback, buf, bufsize);
570 return bufsize;
fae05df5
GL
571}
572
573bool wxInputStream::Ungetch(char c)
1e3eca9d 574{
c7a9fa36
RR
575 char * ptrback = AllocSpaceWBack(1);
576 if (!ptrback)
577 return FALSE;
1e3eca9d 578
c7a9fa36
RR
579 *ptrback = c;
580 return TRUE;
fae05df5
GL
581}
582
583char wxInputStream::GetC()
584{
c7a9fa36
RR
585 char c;
586 Read(&c, 1);
587 return c;
1e3eca9d
GL
588}
589
6d44bf31
GL
590wxInputStream& wxInputStream::Read(void *buffer, size_t size)
591{
c7a9fa36 592 char *buf = (char *)buffer;
fae05df5 593
c7a9fa36 594 size_t retsize = GetWBack(buf, size);
cd6ce4a9 595 if (retsize == size)
c7a9fa36
RR
596 {
597 m_lastcount = size;
598 m_lasterror = wxStream_NOERROR;
599 return *this;
600 }
601 size -= retsize;
602 buf += retsize;
fae05df5 603
c7a9fa36
RR
604 m_lastcount = OnSysRead(buf, size) + retsize;
605 return *this;
3d4c6a21
GL
606}
607
75ed1d15
GL
608char wxInputStream::Peek()
609{
c7a9fa36
RR
610 char c;
611 Read(&c, 1);
cd6ce4a9 612 if (m_lasterror == wxStream_NOERROR)
c7a9fa36
RR
613 {
614 Ungetch(c);
615 return c;
616 }
cd6ce4a9 617
c7a9fa36 618 return 0;
75ed1d15
GL
619}
620
3d4c6a21
GL
621wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
622{
cd6ce4a9 623 char buf[BUF_TEMP_SIZE];
c7a9fa36 624 size_t bytes_read = BUF_TEMP_SIZE;
3d4c6a21 625
cd6ce4a9 626 while (bytes_read == BUF_TEMP_SIZE)
c7a9fa36
RR
627 {
628 bytes_read = Read(buf, bytes_read).LastRead();
629 bytes_read = stream_out.Write(buf, bytes_read).LastWrite();
630 }
631 return *this;
3d4c6a21
GL
632}
633
75ed1d15
GL
634off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
635{
c7a9fa36
RR
636 /* Should be check and improve, just to remove a slight bug !
637 I don't know whether it should be put as well in wxFileInputStream::OnSysSeek ? */
cd6ce4a9 638 if (m_lasterror==wxSTREAM_EOF)
c7a9fa36
RR
639 m_lasterror=wxSTREAM_NOERROR;
640
641 /* A call to SeekI() will automatically invalidate any previous call
642 to Ungetch(), otherwise it would be possible to SeekI() to one
643 one position, unread some bytes there, SeekI() to another position
19da7237
GRG
644 and the data would be corrupted.
645
646 GRG: Could add code here to try to navigate within the wback
647 buffer if possible, but is it really needed? It would only work
648 when seeking in wxFromCurrent mode, else it would invalidate
649 anyway...
650 */
cd6ce4a9 651 if (m_wback)
c7a9fa36
RR
652 {
653 free(m_wback);
654 m_wback = (char*) NULL;
655 m_wbacksize = 0;
656 m_wbackcur = 0;
657 }
fe8aa971 658
c7a9fa36 659 return OnSysSeek(pos, mode);
75ed1d15
GL
660}
661
662off_t wxInputStream::TellI() const
663{
19da7237
GRG
664 /* GRG: Changed to make it compatible with the wback buffer */
665 off_t pos = OnSysTell();
666
667 if (pos != wxInvalidOffset)
668 pos -= (m_wbacksize - m_wbackcur);
669
670 return pos;
75ed1d15
GL
671}
672
673// --------------------
674// Overloaded operators
675// --------------------
676
fae05df5
GL
677#if wxUSE_SERIAL
678wxInputStream& wxInputStream::operator>>(wxObject *& obj)
1678ad78 679{
c7a9fa36
RR
680 wxObjectInputStream obj_s(*this);
681 obj = obj_s.LoadObject();
682 return *this;
1678ad78 683}
fae05df5 684#endif
1678ad78 685
1678ad78 686
fae05df5
GL
687// ----------------------------------------------------------------------------
688// wxOutputStream
689// ----------------------------------------------------------------------------
690wxOutputStream::wxOutputStream()
691 : wxStreamBase()
1678ad78 692{
1678ad78
GL
693}
694
fae05df5 695wxOutputStream::~wxOutputStream()
123a7fdd 696{
123a7fdd
GL
697}
698
7513f9ff
GRG
699void wxOutputStream::PutC(char c)
700{
c7a9fa36 701 Write((void *) &c, 1);
7513f9ff
GRG
702}
703
fae05df5 704wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
1678ad78 705{
c7a9fa36
RR
706 m_lastcount = OnSysWrite(buffer, size);
707 return *this;
1678ad78
GL
708}
709
fae05df5 710wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
38830220 711{
c7a9fa36
RR
712 stream_in.Read(*this);
713 return *this;
38830220
RR
714}
715
fae05df5 716off_t wxOutputStream::TellO() const
38830220 717{
c7a9fa36 718 return OnSysTell();
38830220
RR
719}
720
fae05df5 721off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
38830220 722{
c7a9fa36 723 return OnSysSeek(pos, mode);
38830220
RR
724}
725
fae05df5 726void wxOutputStream::Sync()
1678ad78 727{
1678ad78
GL
728}
729
47d67540 730#if wxUSE_SERIAL
fae05df5 731wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
123a7fdd 732{
c7a9fa36
RR
733 wxObjectOutputStream obj_s(*this);
734 obj_s.SaveObject(obj);
735 return *this;
123a7fdd 736}
fcc6dddd 737#endif
123a7fdd 738
e2acb9ae
RR
739// ----------------------------------------------------------------------------
740// wxCountingOutputStream
741// ----------------------------------------------------------------------------
742
743wxCountingOutputStream::wxCountingOutputStream ()
744 : wxOutputStream()
745{
c7a9fa36 746 m_currentPos = 0;
e2acb9ae
RR
747}
748
749size_t wxCountingOutputStream::GetSize() const
750{
c7a9fa36 751 return m_lastcount;
e2acb9ae
RR
752}
753
5e0201ea 754size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size)
e2acb9ae 755{
c7a9fa36
RR
756 m_currentPos += size;
757 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
758 return m_currentPos;
e2acb9ae
RR
759}
760
761off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
762{
c7a9fa36
RR
763 if (mode == wxFromStart)
764 m_currentPos = pos;
765 if (mode == wxFromEnd)
766 m_currentPos = m_lastcount + pos;
767 else
768 m_currentPos += pos;
cd6ce4a9 769
c7a9fa36 770 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
cd6ce4a9 771
c7a9fa36 772 return m_currentPos;
e2acb9ae
RR
773}
774
775off_t wxCountingOutputStream::OnSysTell() const
776{
c7a9fa36 777 return m_currentPos;
e2acb9ae 778}
cd6ce4a9 779
1678ad78 780// ----------------------------------------------------------------------------
fae05df5 781// wxFilterInputStream
1678ad78 782// ----------------------------------------------------------------------------
e2acb9ae 783
fae05df5
GL
784wxFilterInputStream::wxFilterInputStream()
785 : wxInputStream()
3d4c6a21 786{
6d44bf31
GL
787}
788
fae05df5
GL
789wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
790 : wxInputStream()
6d44bf31 791{
c7a9fa36 792 m_parent_i_stream = &stream;
3d4c6a21
GL
793}
794
fae05df5 795wxFilterInputStream::~wxFilterInputStream()
3d4c6a21 796{
6d44bf31
GL
797}
798
fae05df5
GL
799// ----------------------------------------------------------------------------
800// wxFilterOutputStream
801// ----------------------------------------------------------------------------
802wxFilterOutputStream::wxFilterOutputStream()
803 : wxOutputStream()
6d44bf31 804{
3d4c6a21
GL
805}
806
fae05df5
GL
807wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
808 : wxOutputStream()
3d4c6a21 809{
c7a9fa36 810 m_parent_o_stream = &stream;
6d44bf31
GL
811}
812
fae05df5 813wxFilterOutputStream::~wxFilterOutputStream()
6d44bf31 814{
6d44bf31
GL
815}
816
fae05df5
GL
817// ----------------------------------------------------------------------------
818// wxBufferedInputStream
819// ----------------------------------------------------------------------------
820wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s)
821 : wxFilterInputStream(s)
6d44bf31 822{
c7a9fa36
RR
823 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
824 m_i_streambuf->SetBufferIO(1024);
6d44bf31
GL
825}
826
fae05df5 827wxBufferedInputStream::~wxBufferedInputStream()
6d44bf31 828{
c7a9fa36
RR
829 off_t unused_bytes=m_i_streambuf->GetBufferPos()-m_i_streambuf->GetBufferEnd();
830 m_parent_i_stream->SeekI(unused_bytes,wxFromCurrent);
672cedf8 831
c7a9fa36 832 delete m_i_streambuf;
6d44bf31
GL
833}
834
6319afe3
GL
835char wxBufferedInputStream::Peek()
836{
c7a9fa36 837 return m_i_streambuf->Peek();
6319afe3
GL
838}
839
fae05df5 840wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size)
1e3eca9d 841{
c7a9fa36
RR
842 size_t retsize;
843 char *buf = (char *)buffer;
1e3eca9d 844
c7a9fa36
RR
845 retsize = GetWBack(buf, size);
846 m_lastcount = retsize;
cd6ce4a9 847 if (retsize == size)
c7a9fa36
RR
848 {
849 m_lasterror = wxStream_NOERROR;
850 return *this;
851 }
852 size -= retsize;
853 buf += retsize;
1e3eca9d 854
c7a9fa36 855 m_i_streambuf->Read(buf, size);
6d44bf31 856
c7a9fa36 857 return *this;
6d44bf31
GL
858}
859
fae05df5 860off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
6d44bf31 861{
c7a9fa36 862 return m_i_streambuf->Seek(pos, mode);
6d44bf31
GL
863}
864
fae05df5 865off_t wxBufferedInputStream::TellI() const
6d44bf31 866{
c7a9fa36 867 return m_i_streambuf->Tell();
38830220 868}
6d44bf31 869
fae05df5 870size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
38830220 871{
c7a9fa36 872 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
38830220
RR
873}
874
fae05df5 875off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
38830220 876{
c7a9fa36 877 return m_parent_i_stream->SeekI(seek, mode);
6d44bf31
GL
878}
879
fae05df5 880off_t wxBufferedInputStream::OnSysTell() const
6d44bf31 881{
c7a9fa36 882 return m_parent_i_stream->TellI();
38830220 883}
6d44bf31 884
c7a9fa36 885
fae05df5
GL
886// ----------------------------------------------------------------------------
887// wxBufferedOutputStream
888// ----------------------------------------------------------------------------
6d44bf31 889
fae05df5
GL
890wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s)
891 : wxFilterOutputStream(s)
6d44bf31 892{
c7a9fa36
RR
893 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
894 m_o_streambuf->SetBufferIO(1024);
6d44bf31
GL
895}
896
fae05df5 897wxBufferedOutputStream::~wxBufferedOutputStream()
6d44bf31 898{
c7a9fa36
RR
899 Sync();
900 delete m_o_streambuf;
3d4c6a21
GL
901}
902
fae05df5 903wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
123a7fdd 904{
c7a9fa36
RR
905 m_lastcount = 0;
906 m_o_streambuf->Write(buffer, size);
907 return *this;
123a7fdd
GL
908}
909
fae05df5 910off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
f4ada568 911{
c7a9fa36
RR
912 Sync();
913 return m_o_streambuf->Seek(pos, mode);
f4ada568
GL
914}
915
fae05df5 916off_t wxBufferedOutputStream::TellO() const
3d4c6a21 917{
c7a9fa36 918 return m_o_streambuf->Tell();
3d4c6a21
GL
919}
920
fae05df5 921void wxBufferedOutputStream::Sync()
3d4c6a21 922{
c7a9fa36
RR
923 m_o_streambuf->FlushBuffer();
924 m_parent_o_stream->Sync();
3d4c6a21 925}
219f895a 926
fae05df5 927size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
f4ada568 928{
c7a9fa36 929 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
f4ada568
GL
930}
931
fae05df5 932off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
219f895a 933{
c7a9fa36 934 return m_parent_o_stream->SeekO(seek, mode);
219f895a
RR
935}
936
fae05df5 937off_t wxBufferedOutputStream::OnSysTell() const
219f895a 938{
c7a9fa36
RR
939 return m_parent_o_stream->TellO();
940}
941
942size_t wxBufferedOutputStream::GetSize() const
943{
944 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
219f895a 945}
6d44bf31 946
6d44bf31
GL
947// ----------------------------------------------------------------------------
948// Some IOManip function
949// ----------------------------------------------------------------------------
950
951wxOutputStream& wxEndL(wxOutputStream& stream)
952{
953#ifdef __MSW__
954 return stream.Write("\r\n", 2);
1e3eca9d
GL
955#else
956#ifdef __WXMAC__
957 return stream.Write("\r", 1);
6d44bf31
GL
958#else
959 return stream.Write("\n", 1);
960#endif
1e3eca9d 961#endif
6d44bf31 962}
ce4169a4
RR
963
964#endif
965 // wxUSE_STREAMS