]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/stream.cpp
no message
[wxWidgets.git] / src / common / stream.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: stream.cpp
3// Purpose: wxStream base classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 11/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Guilhem Lavaux
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "stream.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18#include <ctype.h>
19#include <wx/stream.h>
20#include <wx/datstrm.h>
21#include <wx/objstrm.h>
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
27// ----------------------------------------------------------------------------
28// wxStreamBuffer
29// ----------------------------------------------------------------------------
30
31wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
32 : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
33 m_buffer_size(0), m_stream(&stream), m_mode(mode)
34{
35}
36
37wxStreamBuffer::~wxStreamBuffer()
38{
39 wxDELETEA(m_buffer_start);
40}
41
42bool wxStreamBuffer::WriteBack(const char *buf, size_t bufsize)
43{
44 char *ptrback;
45
46 ptrback = AllocSpaceWBack(bufsize);
47 if (!ptrback)
48 return FALSE;
49
50 memcpy(ptrback, buf, bufsize);
51 return TRUE;
52}
53
54bool wxStreamBuffer::WriteBack(char c)
55{
56 char *ptrback;
57
58 ptrback = AllocSpaceWBack(1);
59 if (!ptrback)
60 return FALSE;
61
62 *ptrback = c;
63 return TRUE;
64}
65
66void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end)
67{
68 m_buffer_start = buffer_start;
69 m_buffer_end = buffer_end;
70
71 m_buffer_size = m_buffer_end-m_buffer_start;
72 ResetBuffer();
73}
74
75void wxStreamBuffer::SetBufferIO(size_t bufsize)
76{
77 char *b_start;
78
79 wxDELETE(m_buffer_start);
80
81 if (!bufsize) {
82 m_buffer_start = NULL;
83 m_buffer_end = NULL;
84 m_buffer_pos = NULL;
85 m_buffer_size = 0;
86 return;
87 }
88
89 b_start = new char[bufsize];
90
91 SetBufferIO(b_start, b_start + bufsize);
92}
93
94void wxStreamBuffer::ResetBuffer()
95{
96 if (m_mode == read)
97 m_buffer_pos = m_buffer_end;
98 else
99 m_buffer_pos = m_buffer_start;
100}
101
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
194void wxStreamBuffer::Read(void *buffer, size_t size)
195{
196 wxASSERT(m_stream != NULL);
197
198 // ------------------
199 // Buffering disabled
200 // ------------------
201
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
209 if (!m_buffer_size) {
210 m_stream->m_lastcount += m_stream->OnSysRead(buffer, size);
211 return;
212 }
213
214 // -----------------
215 // Buffering enabled
216 // -----------------
217 size_t buf_left, orig_size = size;
218
219 while (size > 0) {
220 buf_left = GetDataLeft();
221
222 // First case: the requested buffer is larger than the stream buffer,
223 // we split
224 if (size > buf_left) {
225 GetFromBuffer(buffer, buf_left);
226 size -= buf_left;
227 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
228
229 if (!FillBuffer()) {
230 m_stream->m_lastcount = orig_size-size;
231 return;
232 }
233 } else {
234
235 // Second case: we just copy from the stream buffer.
236 GetFromBuffer(buffer, size);
237 break;
238 }
239 }
240 m_stream->m_lastcount += orig_size;
241}
242
243void wxStreamBuffer::Write(const void *buffer, size_t size)
244{
245 wxASSERT(m_stream != NULL);
246
247 // ------------------
248 // Buffering disabled
249 // ------------------
250
251 if (!m_buffer_size) {
252 m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size);
253 return;
254 }
255
256 // ------------------
257 // Buffering enabled
258 // ------------------
259
260 size_t buf_left, orig_size = size;
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) {
268 PutToBuffer(buffer, buf_left);
269 size -= buf_left;
270 buffer = (char *)buffer + buf_left; // ANSI C++ violation.
271
272 if (!FlushBuffer()) {
273 m_stream->m_lastcount = orig_size-size;
274 return;
275 }
276 m_buffer_pos = m_buffer_start;
277
278 } else {
279
280 // Second case: just copy it in the stream buffer.
281 PutToBuffer(buffer, size);
282 break;
283 }
284 }
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;
370}
371
372// ----------------------------------------------------------------------------
373// wxInputStream
374// ----------------------------------------------------------------------------
375
376wxInputStream::wxInputStream()
377 : wxStreamBase()
378{
379 m_i_destroybuf = TRUE;
380 m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read);
381}
382
383wxInputStream::wxInputStream(wxStreamBuffer *buffer)
384 : wxStreamBase()
385{
386 m_i_destroybuf = FALSE;
387 m_i_streambuf = buffer;
388}
389
390wxInputStream::~wxInputStream()
391{
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;
408}
409
410char wxInputStream::Peek()
411{
412 if (!m_i_streambuf->GetDataLeft())
413 m_i_streambuf->FillBuffer();
414
415 return *(m_i_streambuf->GetBufferPos());
416}
417
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
425 while (bytes_read == BUF_TEMP_SIZE && stream_out.LastError() != wxStream_NOERROR) {
426 bytes_read = Read(buf, bytes_read).LastRead();
427
428 stream_out.Write(buf, bytes_read);
429 }
430 return *this;
431}
432
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
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();
458 return *this;
459}
460
461wxInputStream& wxInputStream::operator>>(short& i)
462{
463 long l;
464
465 *this >> l;
466 i = (short)l;
467 return *this;
468}
469
470wxInputStream& wxInputStream::operator>>(int& i)
471{
472 long l;
473
474 *this >> l;
475 i = (short)l;
476 return *this;
477}
478
479wxInputStream& wxInputStream::operator>>(long& i)
480{
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
506 return *this;
507}
508
509wxInputStream& wxInputStream::operator>>(double& f)
510{
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)) {
530 f = f*10 + (c - '0');
531 c = GetC();
532 }
533
534 if (c == '.') {
535 double f_multiplicator = (double) 0.1;
536 c = GetC();
537
538 while (isdigit(c)) {
539 f += (c-'0')*f_multiplicator;
540 f_multiplicator /= 10;
541 c = GetC();
542 }
543 }
544
545 f *= sign;
546
547 return *this;
548}
549
550#if wxUSE_SERIAL
551wxInputStream& wxInputStream::operator>>(wxObject *& obj)
552{
553 wxObjectInputStream obj_s(*this);
554 obj = obj_s.LoadObject();
555 return *this;
556}
557#endif
558
559
560// ----------------------------------------------------------------------------
561// wxOutputStream
562// ----------------------------------------------------------------------------
563wxOutputStream::wxOutputStream()
564 : wxStreamBase()
565{
566 m_o_destroybuf = TRUE;
567 m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
568}
569
570wxOutputStream::wxOutputStream(wxStreamBuffer *buffer)
571 : wxStreamBase()
572{
573 m_o_destroybuf = FALSE;
574 m_o_streambuf = buffer;
575}
576
577wxOutputStream::~wxOutputStream()
578{
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;
587}
588
589wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
590{
591 stream_in.Read(*this);
592 return *this;
593}
594
595off_t wxOutputStream::TellO() const
596{
597 return m_o_streambuf->Tell();
598}
599
600off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
601{
602 return m_o_streambuf->Seek(pos, mode);
603}
604
605void wxOutputStream::Sync()
606{
607 m_o_streambuf->FlushBuffer();
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());
655}
656
657#if wxUSE_SERIAL
658wxOutputStream& wxOutputStream::operator<<(wxObject& obj)
659{
660 wxObjectOutputStream obj_s(*this);
661 obj_s.SaveObject(obj);
662 return *this;
663}
664#endif
665
666// ----------------------------------------------------------------------------
667// wxFilterInputStream
668// ----------------------------------------------------------------------------
669wxFilterInputStream::wxFilterInputStream()
670 : wxInputStream(NULL)
671{
672 // WARNING streambuf set to NULL !
673}
674
675wxFilterInputStream::wxFilterInputStream(wxInputStream& stream)
676 : wxInputStream(stream.InputStreamBuffer())
677{
678 m_parent_i_stream = &stream;
679}
680
681wxFilterInputStream::~wxFilterInputStream()
682{
683}
684
685// ----------------------------------------------------------------------------
686// wxFilterOutputStream
687// ----------------------------------------------------------------------------
688wxFilterOutputStream::wxFilterOutputStream()
689 : wxOutputStream(NULL)
690{
691}
692
693wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream)
694 : wxOutputStream(stream.OutputStreamBuffer())
695{
696 m_parent_o_stream = &stream;
697}
698
699wxFilterOutputStream::~wxFilterOutputStream()
700{
701}
702
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}