]> git.saurik.com Git - wxWidgets.git/blame - src/common/stream.cpp
no message
[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"
6d44bf31 18#include <ctype.h>
79c3e0e1 19#include <wx/stream.h>
6d44bf31 20#include <wx/datstrm.h>
123a7fdd 21#include <wx/objstrm.h>
db138a4c
JS
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
6d44bf31
GL
27// ----------------------------------------------------------------------------
28// wxStreamBuffer
29// ----------------------------------------------------------------------------
30
75ed1d15 31wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
6d44bf31 32 : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
75ed1d15 33 m_buffer_size(0), m_stream(&stream), m_mode(mode)
6d44bf31
GL
34{
35}
36
75ed1d15 37wxStreamBuffer::~wxStreamBuffer()
6d44bf31 38{
75ed1d15 39 wxDELETEA(m_buffer_start);
6d44bf31
GL
40}
41
75ed1d15 42bool wxStreamBuffer::WriteBack(const char *buf, size_t bufsize)
6d44bf31 43{
75ed1d15
GL
44 char *ptrback;
45
46 ptrback = AllocSpaceWBack(bufsize);
47 if (!ptrback)
48 return FALSE;
49
50 memcpy(ptrback, buf, bufsize);
51 return TRUE;
6d44bf31
GL
52}
53
75ed1d15 54bool wxStreamBuffer::WriteBack(char c)
6d44bf31 55{
75ed1d15 56 char *ptrback;
6d44bf31 57
75ed1d15
GL
58 ptrback = AllocSpaceWBack(1);
59 if (!ptrback)
60 return FALSE;
6d44bf31 61
75ed1d15
GL
62 *ptrback = c;
63 return TRUE;
6d44bf31
GL
64}
65
66void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end)
67{
885ee235
GL
68 m_buffer_start = buffer_start;
69 m_buffer_end = buffer_end;
6d44bf31
GL
70
71 m_buffer_size = m_buffer_end-m_buffer_start;
75ed1d15 72 ResetBuffer();
6d44bf31
GL
73}
74
75void wxStreamBuffer::SetBufferIO(size_t bufsize)
76{
885ee235
GL
77 char *b_start;
78
79 wxDELETE(m_buffer_start);
6d44bf31
GL
80
81 if (!bufsize) {
82 m_buffer_start = NULL;
83 m_buffer_end = NULL;
84 m_buffer_pos = NULL;
85 m_buffer_size = 0;
885ee235 86 return;
6d44bf31
GL
87 }
88
885ee235
GL
89 b_start = new char[bufsize];
90
91 SetBufferIO(b_start, b_start + bufsize);
6d44bf31
GL
92}
93
94void wxStreamBuffer::ResetBuffer()
95{
75ed1d15 96 if (m_mode == read)
6d44bf31
GL
97 m_buffer_pos = m_buffer_end;
98 else
99 m_buffer_pos = m_buffer_start;
100}
101
75ed1d15
GL
102char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size)
103{
104 char *temp_b;
105
106 m_wbacksize += needed_size;
107
108 if (!m_wback)
109 temp_b = (char *)malloc(m_wbacksize);
110 else
111 temp_b = (char *)realloc(m_wback, m_wbacksize);
112
113 if (!temp_b)
114 return NULL;
115 return (char *)((size_t)m_wback+(m_wbacksize-needed_size));
116}
117
118size_t wxStreamBuffer::GetWBack(char *buf, size_t bsize)
119{
120 size_t s_toget = m_wbacksize-m_wbackcur;
121
122 if (bsize < s_toget)
123 s_toget = bsize;
124
125 memcpy(buf, (m_wback+m_wbackcur), s_toget);
126
127 m_wbackcur += s_toget;
128 if (m_wbackcur == m_wbacksize) {
129 free(m_wback);
130 m_wback = (char *)NULL;
131 m_wbacksize = 0;
132 m_wbackcur = 0;
133 }
134
135 return s_toget;
136}
137
138bool wxStreamBuffer::FillBuffer()
139{
140 size_t count;
141
142 count = m_stream->OnSysRead(m_buffer_start, m_buffer_size);
143 m_buffer_end = m_buffer_start+count;
144 m_buffer_pos = m_buffer_start;
145
146 if (count == 0)
147 return FALSE;
148 return TRUE;
149}
150
151bool wxStreamBuffer::FlushBuffer()
152{
153 size_t count, current;
154
155 if (m_buffer_pos == m_buffer_start)
156 return FALSE;
157
158 current = m_buffer_pos-m_buffer_start;
159 count = m_stream->OnSysWrite(m_buffer_start, current);
160 if (count != current)
161 return FALSE;
162 m_buffer_pos = m_buffer_start;
163
164 return TRUE;
165}
166
167void wxStreamBuffer::GetFromBuffer(void *buffer, size_t size)
168{
169 size_t s_toget = m_buffer_end-m_buffer_pos;
170
171 if (size < s_toget)
172 s_toget = size;
173
174 memcpy(buffer, m_buffer_pos, s_toget);
175 m_buffer_pos += s_toget;
176}
177
178void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size)
179{
180 size_t s_toput = m_buffer_end-m_buffer_pos;
181
182 if (s_toput < size && !m_fixed) {
183 m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size);
184 // I round a bit
185 m_buffer_end = m_buffer_start+m_buffer_size;
186 s_toput = size;
187 }
188 if (s_toput > size)
189 s_toput = size;
190 memcpy(m_buffer_pos, buffer, s_toput);
191 m_buffer_pos += s_toput;
192}
193
6d44bf31
GL
194void wxStreamBuffer::Read(void *buffer, size_t size)
195{
75ed1d15 196 wxASSERT(m_stream != NULL);
6d44bf31
GL
197
198 // ------------------
199 // Buffering disabled
200 // ------------------
201
75ed1d15
GL
202 m_stream->m_lastcount = GetWBack((char *)buffer, size);
203 size -= m_stream->m_lastcount;
204 if (size == 0)
205 return;
206
207 buffer = (void *)((char *)buffer+m_stream->m_lastcount);
208
6d44bf31 209 if (!m_buffer_size) {
75ed1d15 210 m_stream->m_lastcount += m_stream->OnSysRead(buffer, size);
6d44bf31
GL
211 return;
212 }
213
214 // -----------------
215 // Buffering enabled
216 // -----------------
217 size_t buf_left, orig_size = size;
6d44bf31
GL
218
219 while (size > 0) {
75ed1d15 220 buf_left = GetDataLeft();
6d44bf31
GL
221
222 // First case: the requested buffer is larger than the stream buffer,
223 // we split
224 if (size > buf_left) {
75ed1d15
GL
225 GetFromBuffer(buffer, buf_left);
226 size -= buf_left;
6d44bf31
GL
227 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
228
75ed1d15
GL
229 if (!FillBuffer()) {
230 m_stream->m_lastcount = orig_size-size;
6d44bf31 231 return;
6d44bf31
GL
232 }
233 } else {
234
235 // Second case: we just copy from the stream buffer.
75ed1d15 236 GetFromBuffer(buffer, size);
6d44bf31
GL
237 break;
238 }
239 }
75ed1d15 240 m_stream->m_lastcount += orig_size;
6d44bf31
GL
241}
242
243void wxStreamBuffer::Write(const void *buffer, size_t size)
244{
75ed1d15 245 wxASSERT(m_stream != NULL);
6d44bf31
GL
246
247 // ------------------
248 // Buffering disabled
249 // ------------------
250
251 if (!m_buffer_size) {
75ed1d15 252 m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size);
6d44bf31
GL
253 return;
254 }
255
256 // ------------------
257 // Buffering enabled
258 // ------------------
259
260 size_t buf_left, orig_size = size;
6d44bf31
GL
261
262 while (size > 0) {
263 buf_left = m_buffer_end - m_buffer_pos;
264
265 // First case: the buffer to write is larger than the stream buffer,
266 // we split it
267 if (size > buf_left) {
75ed1d15 268 PutToBuffer(buffer, buf_left);
6d44bf31
GL
269 size -= buf_left;
270 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
271
75ed1d15
GL
272 if (!FlushBuffer()) {
273 m_stream->m_lastcount = orig_size-size;
6d44bf31
GL
274 return;
275 }
276 m_buffer_pos = m_buffer_start;
277
278 } else {
279
280 // Second case: just copy it in the stream buffer.
75ed1d15 281 PutToBuffer(buffer, size);
6d44bf31
GL
282 break;
283 }
284 }
75ed1d15
GL
285 m_stream->m_lastcount = orig_size;
286}
287
288off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
289{
290 off_t ret_off, diff, last_access;
291
292 last_access = GetLastAccess();
293
294 switch (mode) {
295 case wxFromStart: {
296 // We'll try to compute an internal position later ...
297 ret_off = m_stream->OnSysSeek(pos, wxFromStart);
298 ResetBuffer();
299 return ret_off;
300 }
301 case wxFromCurrent: {
302 diff = pos + GetIntPosition();
303
304 if ( (diff > last_access) || (diff < 0) ) {
305 ret_off = m_stream->OnSysSeek(pos, wxFromCurrent);
306 ResetBuffer();
307 return ret_off;
308 } else {
309 SetIntPosition(diff);
310 return pos;
311 }
312 }
313 case wxFromEnd:
314 // Hard to compute: always seek to the requested position.
315 ret_off = m_stream->OnSysSeek(pos, wxFromEnd);
316 ResetBuffer();
317 return ret_off;
318 }
319 return wxInvalidOffset;
320}
321
322off_t wxStreamBuffer::Tell() const
323{
324 off_t pos;
325
326 pos = m_stream->OnSysTell();
327 if (pos == wxInvalidOffset)
328 return wxInvalidOffset;
329
330 return pos - GetLastAccess() + GetIntPosition();
331}
332
333size_t wxStreamBuffer::GetDataLeft() const
334{
335 return m_buffer_end-m_buffer_pos;
336}
337
338// ----------------------------------------------------------------------------
339// wxStreamBase
340// ----------------------------------------------------------------------------
341
342wxStreamBase::wxStreamBase()
343{
344 m_lasterror = wxStream_NOERROR;
345 m_lastcount = 0;
346}
347
348wxStreamBase::~wxStreamBase()
349{
350}
351
352size_t wxStreamBase::OnSysRead(void *buffer, size_t size)
353{
354 return 0;
355}
356
357size_t wxStreamBase::OnSysWrite(const void *buffer, size_t bufsize)
358{
359 return 0;
360}
361
362off_t wxStreamBase::OnSysSeek(off_t seek, wxSeekMode mode)
363{
364 return wxInvalidOffset;
365}
366
367off_t wxStreamBase::OnSysTell()
368{
369 return wxInvalidOffset;
6d44bf31
GL
370}
371
1678ad78
GL
372// ----------------------------------------------------------------------------
373// wxInputStream
374// ----------------------------------------------------------------------------
375
3d4c6a21 376wxInputStream::wxInputStream()
75ed1d15 377 : wxStreamBase()
3d4c6a21 378{
6d44bf31 379 m_i_destroybuf = TRUE;
75ed1d15 380 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
6d44bf31
GL
381}
382
383wxInputStream::wxInputStream(wxStreamBuffer *buffer)
75ed1d15 384 : wxStreamBase()
6d44bf31
GL
385{
386 m_i_destroybuf = FALSE;
387 m_i_streambuf = buffer;
3d4c6a21
GL
388}
389
390wxInputStream::~wxInputStream()
391{
6d44bf31
GL
392 if (m_i_destroybuf)
393 delete m_i_streambuf;
394}
395
396char wxInputStream::GetC()
397{
398 char c;
399 m_i_streambuf->Read(&c, 1);
400 return c;
401}
402
403wxInputStream& wxInputStream::Read(void *buffer, size_t size)
404{
405 m_i_streambuf->Read(buffer, size);
406 // wxStreamBuffer sets all variables for us
407 return *this;
3d4c6a21
GL
408}
409
75ed1d15
GL
410char wxInputStream::Peek()
411{
412 if (!m_i_streambuf->GetDataLeft())
413 m_i_streambuf->FillBuffer();
414
415 return *(m_i_streambuf->GetBufferPos());
416}
417
3d4c6a21
GL
418#define BUF_TEMP_SIZE 10000
419
420wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
421{
422 char buf[BUF_TEMP_SIZE];
423 size_t bytes_read = BUF_TEMP_SIZE;
424
75ed1d15 425 while (bytes_read == BUF_TEMP_SIZE && stream_out.LastError() != wxStream_NOERROR) {
3d4c6a21
GL
426 bytes_read = Read(buf, bytes_read).LastRead();
427
428 stream_out.Write(buf, bytes_read);
429 }
430 return *this;
431}
432
75ed1d15
GL
433off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
434{
435 return m_i_streambuf->Seek(pos, mode);
436}
437
438off_t wxInputStream::TellI() const
439{
440 return m_i_streambuf->Tell();
441}
442
443// --------------------
444// Overloaded operators
445// --------------------
446
1678ad78
GL
447wxInputStream& wxInputStream::operator>>(wxString& line)
448{
449 wxDataInputStream s(*this);
450
451 line = s.ReadLine();
452 return *this;
453}
454
455wxInputStream& wxInputStream::operator>>(char& c)
456{
457 c = GetC();
6d44bf31 458 return *this;
1678ad78
GL
459}
460
461wxInputStream& wxInputStream::operator>>(short& i)
462{
6d44bf31
GL
463 long l;
464
465 *this >> l;
466 i = (short)l;
1678ad78
GL
467 return *this;
468}
469
123a7fdd
GL
470wxInputStream& wxInputStream::operator>>(int& i)
471{
472 long l;
473
474 *this >> l;
475 i = (short)l;
476 return *this;
477}
478
1678ad78
GL
479wxInputStream& wxInputStream::operator>>(long& i)
480{
6d44bf31
GL
481 /* I only implemented a simple integer parser */
482 int c, sign;
483
484 while (isspace( c = GetC() ) )
485 /* Do nothing */ ;
486
487 i = 0;
488 if (! (c == '-' || isdigit(c)) ) {
489 InputStreamBuffer()->WriteBack(c);
490 return *this;
491 }
492
493 if (c == '-') {
494 sign = -1;
495 c = GetC();
496 } else
497 sign = 1;
498
499 while (isdigit(c)) {
500 i = i*10 + c;
501 c = GetC();
502 }
503
504 i *= sign;
505
1678ad78
GL
506 return *this;
507}
508
75ed1d15 509wxInputStream& wxInputStream::operator>>(double& f)
1678ad78 510{
6d44bf31
GL
511 /* I only implemented a simple float parser */
512 int c, sign;
513
514 while (isspace( c = GetC() ) )
515 /* Do nothing */ ;
516
517 f = 0.0;
518 if (! (c == '-' || isdigit(c)) ) {
519 InputStreamBuffer()->WriteBack(c);
520 return *this;
521 }
522
523 if (c == '-') {
524 sign = -1;
525 c = GetC();
526 } else
527 sign = 1;
528
529 while (isdigit(c)) {
75ed1d15 530 f = f*10 + (c - '0');
6d44bf31
GL
531 c = GetC();
532 }
533
534 if (c == '.') {
75ed1d15 535 double f_multiplicator = (double) 0.1;
6d44bf31
GL
536 c = GetC();
537
538 while (isdigit(c)) {
75ed1d15 539 f += (c-'0')*f_multiplicator;
6d44bf31
GL
540 f_multiplicator /= 10;
541 c = GetC();
542 }
543 }
544
545 f *= sign;
546
1678ad78
GL
547 return *this;
548}
549
47d67540 550#if wxUSE_SERIAL
123a7fdd
GL
551wxInputStream& wxInputStream::operator>>(wxObject *& obj)
552{
553 wxObjectInputStream obj_s(*this);
554 obj = obj_s.LoadObject();
555 return *this;
556}
fcc6dddd 557#endif
123a7fdd 558
6d44bf31 559
1678ad78
GL
560// ----------------------------------------------------------------------------
561// wxOutputStream
562// ----------------------------------------------------------------------------
3d4c6a21 563wxOutputStream::wxOutputStream()
75ed1d15 564 : wxStreamBase()
3d4c6a21 565{
6d44bf31 566 m_o_destroybuf = TRUE;
75ed1d15 567 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
6d44bf31
GL
568}
569
570wxOutputStream::wxOutputStream(wxStreamBuffer *buffer)
75ed1d15 571 : wxStreamBase()
6d44bf31
GL
572{
573 m_o_destroybuf = FALSE;
574 m_o_streambuf = buffer;
3d4c6a21
GL
575}
576
577wxOutputStream::~wxOutputStream()
578{
6d44bf31
GL
579 if (m_o_destroybuf)
580 delete m_o_streambuf;
581}
582
583wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
584{
585 m_o_streambuf->Write(buffer, size);
586 return *this;
3d4c6a21
GL
587}
588
589wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
590{
6d44bf31
GL
591 stream_in.Read(*this);
592 return *this;
593}
594
75ed1d15 595off_t wxOutputStream::TellO() const
6d44bf31 596{
75ed1d15 597 return m_o_streambuf->Tell();
6d44bf31
GL
598}
599
75ed1d15 600off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
6d44bf31 601{
75ed1d15 602 return m_o_streambuf->Seek(pos, mode);
6d44bf31
GL
603}
604
605void wxOutputStream::Sync()
606{
75ed1d15 607 m_o_streambuf->FlushBuffer();
6d44bf31
GL
608}
609
610wxOutputStream& wxOutputStream::operator<<(const char *string)
611{
612 return Write(string, strlen(string));
613}
614
615wxOutputStream& wxOutputStream::operator<<(wxString& string)
616{
617 return Write(string, string.Len());
618}
619
620wxOutputStream& wxOutputStream::operator<<(char c)
621{
622 return Write(&c, 1);
623}
624
625wxOutputStream& wxOutputStream::operator<<(short i)
626{
627 wxString strint;
628
629 strint.Printf("%i", i);
630 return Write(strint, strint.Len());
631}
632
633wxOutputStream& wxOutputStream::operator<<(int i)
634{
635 wxString strint;
636
637 strint.Printf("%i", i);
638 return Write(strint, strint.Len());
639}
640
641wxOutputStream& wxOutputStream::operator<<(long i)
642{
643 wxString strlong;
644
645 strlong.Printf("%i", i);
646 return Write((const char *)strlong, strlong.Len());
647}
648
649wxOutputStream& wxOutputStream::operator<<(double f)
650{
651 wxString strfloat;
652
653 strfloat.Printf("%f", f);
654 return Write(strfloat, strfloat.Len());
3d4c6a21
GL
655}
656
47d67540 657#if wxUSE_SERIAL
123a7fdd
GL
658wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
659{
660 wxObjectOutputStream obj_s(*this);
661 obj_s.SaveObject(obj);
662 return *this;
663}
fcc6dddd 664#endif
123a7fdd 665
1678ad78
GL
666// ----------------------------------------------------------------------------
667// wxFilterInputStream
668// ----------------------------------------------------------------------------
f4ada568
GL
669wxFilterInputStream::wxFilterInputStream()
670 : wxInputStream(NULL)
671{
75ed1d15 672 // WARNING streambuf set to NULL !
f4ada568
GL
673}
674
3d4c6a21 675wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
75ed1d15 676 : wxInputStream(stream.InputStreamBuffer())
3d4c6a21 677{
219f895a 678 m_parent_i_stream = &stream;
3d4c6a21
GL
679}
680
681wxFilterInputStream::~wxFilterInputStream()
682{
683}
219f895a 684
1678ad78
GL
685// ----------------------------------------------------------------------------
686// wxFilterOutputStream
687// ----------------------------------------------------------------------------
f4ada568
GL
688wxFilterOutputStream::wxFilterOutputStream()
689 : wxOutputStream(NULL)
690{
691}
692
219f895a 693wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
75ed1d15 694 : wxOutputStream(stream.OutputStreamBuffer())
219f895a
RR
695{
696 m_parent_o_stream = &stream;
697}
698
699wxFilterOutputStream::~wxFilterOutputStream()
700{
701}
6d44bf31 702
6d44bf31
GL
703// ----------------------------------------------------------------------------
704// Some IOManip function
705// ----------------------------------------------------------------------------
706
707wxOutputStream& wxEndL(wxOutputStream& stream)
708{
709#ifdef __MSW__
710 return stream.Write("\r\n", 2);
711#else
712 return stream.Write("\n", 1);
713#endif
714}