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