]> git.saurik.com Git - wxWidgets.git/blame - src/common/stream.cpp
1. wxGrid row can't be resized to less than minimal height
[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
19da7237
GRG
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 */
c7a9fa36
RR
635 if (m_wback)
636 {
637 free(m_wback);
638 m_wback = (char*) NULL;
639 m_wbacksize = 0;
640 m_wbackcur = 0;
641 }
fe8aa971 642
c7a9fa36 643 return OnSysSeek(pos, mode);
75ed1d15
GL
644}
645
646off_t wxInputStream::TellI() const
647{
19da7237
GRG
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;
75ed1d15
GL
655}
656
657// --------------------
658// Overloaded operators
659// --------------------
660
fae05df5
GL
661#if wxUSE_SERIAL
662wxInputStream& wxInputStream::operator>>(wxObject *& obj)
1678ad78 663{
c7a9fa36
RR
664 wxObjectInputStream obj_s(*this);
665 obj = obj_s.LoadObject();
666 return *this;
1678ad78 667}
fae05df5 668#endif
1678ad78 669
1678ad78 670
fae05df5
GL
671// ----------------------------------------------------------------------------
672// wxOutputStream
673// ----------------------------------------------------------------------------
674wxOutputStream::wxOutputStream()
675 : wxStreamBase()
1678ad78 676{
1678ad78
GL
677}
678
fae05df5 679wxOutputStream::~wxOutputStream()
123a7fdd 680{
123a7fdd
GL
681}
682
7513f9ff
GRG
683void wxOutputStream::PutC(char c)
684{
c7a9fa36 685 Write((void *) &c, 1);
7513f9ff
GRG
686}
687
fae05df5 688wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
1678ad78 689{
c7a9fa36
RR
690 m_lastcount = OnSysWrite(buffer, size);
691 return *this;
1678ad78
GL
692}
693
fae05df5 694wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
38830220 695{
c7a9fa36
RR
696 stream_in.Read(*this);
697 return *this;
38830220
RR
698}
699
fae05df5 700off_t wxOutputStream::TellO() const
38830220 701{
c7a9fa36 702 return OnSysTell();
38830220
RR
703}
704
fae05df5 705off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
38830220 706{
c7a9fa36 707 return OnSysSeek(pos, mode);
38830220
RR
708}
709
fae05df5 710void wxOutputStream::Sync()
1678ad78 711{
1678ad78
GL
712}
713
47d67540 714#if wxUSE_SERIAL
fae05df5 715wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
123a7fdd 716{
c7a9fa36
RR
717 wxObjectOutputStream obj_s(*this);
718 obj_s.SaveObject(obj);
719 return *this;
123a7fdd 720}
fcc6dddd 721#endif
123a7fdd 722
e2acb9ae
RR
723// ----------------------------------------------------------------------------
724// wxCountingOutputStream
725// ----------------------------------------------------------------------------
726
727wxCountingOutputStream::wxCountingOutputStream ()
728 : wxOutputStream()
729{
c7a9fa36 730 m_currentPos = 0;
e2acb9ae
RR
731}
732
733size_t wxCountingOutputStream::GetSize() const
734{
c7a9fa36 735 return m_lastcount;
e2acb9ae
RR
736}
737
5e0201ea 738size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size)
e2acb9ae 739{
c7a9fa36
RR
740 m_currentPos += size;
741 if (m_currentPos > m_lastcount) m_lastcount = m_currentPos;
742 return m_currentPos;
e2acb9ae
RR
743}
744
745off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
746{
c7a9fa36
RR
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;
e2acb9ae 755
c7a9fa36 756 return m_currentPos;
e2acb9ae
RR
757}
758
759off_t wxCountingOutputStream::OnSysTell() const
760{
c7a9fa36 761 return m_currentPos;
e2acb9ae
RR
762}
763
1678ad78 764// ----------------------------------------------------------------------------
fae05df5 765// wxFilterInputStream
1678ad78 766// ----------------------------------------------------------------------------
e2acb9ae 767
fae05df5
GL
768wxFilterInputStream::wxFilterInputStream()
769 : wxInputStream()
3d4c6a21 770{
6d44bf31
GL
771}
772
fae05df5
GL
773wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
774 : wxInputStream()
6d44bf31 775{
c7a9fa36 776 m_parent_i_stream = &stream;
3d4c6a21
GL
777}
778
fae05df5 779wxFilterInputStream::~wxFilterInputStream()
3d4c6a21 780{
6d44bf31
GL
781}
782
fae05df5
GL
783// ----------------------------------------------------------------------------
784// wxFilterOutputStream
785// ----------------------------------------------------------------------------
786wxFilterOutputStream::wxFilterOutputStream()
787 : wxOutputStream()
6d44bf31 788{
3d4c6a21
GL
789}
790
fae05df5
GL
791wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
792 : wxOutputStream()
3d4c6a21 793{
c7a9fa36 794 m_parent_o_stream = &stream;
6d44bf31
GL
795}
796
fae05df5 797wxFilterOutputStream::~wxFilterOutputStream()
6d44bf31 798{
6d44bf31
GL
799}
800
fae05df5
GL
801// ----------------------------------------------------------------------------
802// wxBufferedInputStream
803// ----------------------------------------------------------------------------
804wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s)
805 : wxFilterInputStream(s)
6d44bf31 806{
c7a9fa36
RR
807 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
808 m_i_streambuf->SetBufferIO(1024);
6d44bf31
GL
809}
810
fae05df5 811wxBufferedInputStream::~wxBufferedInputStream()
6d44bf31 812{
c7a9fa36
RR
813 off_t unused_bytes=m_i_streambuf->GetBufferPos()-m_i_streambuf->GetBufferEnd();
814 m_parent_i_stream->SeekI(unused_bytes,wxFromCurrent);
672cedf8 815
c7a9fa36 816 delete m_i_streambuf;
6d44bf31
GL
817}
818
6319afe3
GL
819char wxBufferedInputStream::Peek()
820{
c7a9fa36 821 return m_i_streambuf->Peek();
6319afe3
GL
822}
823
fae05df5 824wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size)
1e3eca9d 825{
c7a9fa36
RR
826 size_t retsize;
827 char *buf = (char *)buffer;
1e3eca9d 828
c7a9fa36
RR
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;
1e3eca9d 838
c7a9fa36 839 m_i_streambuf->Read(buf, size);
6d44bf31 840
c7a9fa36 841 return *this;
6d44bf31
GL
842}
843
fae05df5 844off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
6d44bf31 845{
c7a9fa36 846 return m_i_streambuf->Seek(pos, mode);
6d44bf31
GL
847}
848
fae05df5 849off_t wxBufferedInputStream::TellI() const
6d44bf31 850{
c7a9fa36 851 return m_i_streambuf->Tell();
38830220 852}
6d44bf31 853
fae05df5 854size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
38830220 855{
c7a9fa36 856 return m_parent_i_stream->Read(buffer, bufsize).LastRead();
38830220
RR
857}
858
fae05df5 859off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
38830220 860{
c7a9fa36 861 return m_parent_i_stream->SeekI(seek, mode);
6d44bf31
GL
862}
863
fae05df5 864off_t wxBufferedInputStream::OnSysTell() const
6d44bf31 865{
c7a9fa36 866 return m_parent_i_stream->TellI();
38830220 867}
6d44bf31 868
c7a9fa36 869
fae05df5
GL
870// ----------------------------------------------------------------------------
871// wxBufferedOutputStream
872// ----------------------------------------------------------------------------
6d44bf31 873
fae05df5
GL
874wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s)
875 : wxFilterOutputStream(s)
6d44bf31 876{
c7a9fa36
RR
877 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
878 m_o_streambuf->SetBufferIO(1024);
6d44bf31
GL
879}
880
fae05df5 881wxBufferedOutputStream::~wxBufferedOutputStream()
6d44bf31 882{
c7a9fa36
RR
883 Sync();
884 delete m_o_streambuf;
3d4c6a21
GL
885}
886
fae05df5 887wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
123a7fdd 888{
c7a9fa36
RR
889 m_lastcount = 0;
890 m_o_streambuf->Write(buffer, size);
891 return *this;
123a7fdd
GL
892}
893
fae05df5 894off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
f4ada568 895{
c7a9fa36
RR
896 Sync();
897 return m_o_streambuf->Seek(pos, mode);
f4ada568
GL
898}
899
fae05df5 900off_t wxBufferedOutputStream::TellO() const
3d4c6a21 901{
c7a9fa36 902 return m_o_streambuf->Tell();
3d4c6a21
GL
903}
904
fae05df5 905void wxBufferedOutputStream::Sync()
3d4c6a21 906{
c7a9fa36
RR
907 m_o_streambuf->FlushBuffer();
908 m_parent_o_stream->Sync();
3d4c6a21 909}
219f895a 910
fae05df5 911size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
f4ada568 912{
c7a9fa36 913 return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
f4ada568
GL
914}
915
fae05df5 916off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
219f895a 917{
c7a9fa36 918 return m_parent_o_stream->SeekO(seek, mode);
219f895a
RR
919}
920
fae05df5 921off_t wxBufferedOutputStream::OnSysTell() const
219f895a 922{
c7a9fa36
RR
923 return m_parent_o_stream->TellO();
924}
925
926size_t wxBufferedOutputStream::GetSize() const
927{
928 return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
219f895a 929}
6d44bf31 930
6d44bf31
GL
931// ----------------------------------------------------------------------------
932// Some IOManip function
933// ----------------------------------------------------------------------------
934
935wxOutputStream& wxEndL(wxOutputStream& stream)
936{
937#ifdef __MSW__
938 return stream.Write("\r\n", 2);
1e3eca9d
GL
939#else
940#ifdef __WXMAC__
941 return stream.Write("\r", 1);
6d44bf31
GL
942#else
943 return stream.Write("\n", 1);
944#endif
1e3eca9d 945#endif
6d44bf31 946}
ce4169a4
RR
947
948#endif
949 // wxUSE_STREAMS