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