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