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