1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/stream.h
3 // Purpose:     stream classes
4 // Author:      Guilhem Lavaux, Guillermo Rodriguez Garcia, Vadim Zeitlin
5 // Modified by:
6 // Created:     11/07/98
7 // RCS-ID:      $Id: stream.h 53135 2008-04-12 02:31:04Z VZ $
8 // Copyright:   (c) Guilhem Lavaux
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef _WX_WXSTREAM_H__
13 #define _WX_WXSTREAM_H__
14 
15 #include "wx/defs.h"
16 
17 #if wxUSE_STREAMS
18 
19 #include <stdio.h>
20 #include "wx/object.h"
21 #include "wx/string.h"
22 #include "wx/filefn.h"  // for wxFileOffset, wxInvalidOffset and wxSeekMode
23 
24 class WXDLLIMPEXP_FWD_BASE wxStreamBase;
25 class WXDLLIMPEXP_FWD_BASE wxInputStream;
26 class WXDLLIMPEXP_FWD_BASE wxOutputStream;
27 
28 typedef wxInputStream& (*__wxInputManip)(wxInputStream&);
29 typedef wxOutputStream& (*__wxOutputManip)(wxOutputStream&);
30 
31 WXDLLIMPEXP_BASE wxOutputStream& wxEndL(wxOutputStream& o_stream);
32 
33 // ----------------------------------------------------------------------------
34 // constants
35 // ----------------------------------------------------------------------------
36 
37 enum wxStreamError
38 {
39     wxSTREAM_NO_ERROR = 0,      // stream is in good state
40     wxSTREAM_EOF,               // EOF reached in Read() or similar
41     wxSTREAM_WRITE_ERROR,       // generic write error
42     wxSTREAM_READ_ERROR         // generic read error
43 };
44 
45 const int wxEOF = -1;
46 
47 // ============================================================================
48 // base stream classes: wxInputStream and wxOutputStream
49 // ============================================================================
50 
51 // ---------------------------------------------------------------------------
52 // wxStreamBase: common (but non virtual!) base for all stream classes
53 // ---------------------------------------------------------------------------
54 
55 class WXDLLIMPEXP_BASE wxStreamBase
56 {
57 public:
58     wxStreamBase();
59     virtual ~wxStreamBase();
60 
61     // error testing
GetLastError()62     wxStreamError GetLastError() const { return m_lasterror; }
IsOk()63     virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; }
64     bool operator!() const { return !IsOk(); }
65 
66     // reset the stream state
Reset()67     void Reset() { m_lasterror = wxSTREAM_NO_ERROR; }
68 
69     // this doesn't make sense for all streams, always test its return value
70     virtual size_t GetSize() const;
GetLength()71     virtual wxFileOffset GetLength() const { return wxInvalidOffset; }
72 
73     // returns true if the streams supports seeking to arbitrary offsets
IsSeekable()74     virtual bool IsSeekable() const { return false; }
75 
76 protected:
77     virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
78     virtual wxFileOffset OnSysTell() const;
79 
80     size_t m_lastcount;
81     wxStreamError m_lasterror;
82 
83     friend class wxStreamBuffer;
84 
85     DECLARE_NO_COPY_CLASS(wxStreamBase)
86 };
87 
88 // ----------------------------------------------------------------------------
89 // wxInputStream: base class for the input streams
90 // ----------------------------------------------------------------------------
91 
92 class WXDLLIMPEXP_BASE wxInputStream : public wxStreamBase
93 {
94 public:
95     // ctor and dtor, nothing exciting
96     wxInputStream();
97     virtual ~wxInputStream();
98 
99 
100     // IO functions
101     // ------------
102 
103     // return a character from the stream without removing it, i.e. it will
104     // still be returned by the next call to GetC()
105     //
106     // blocks until something appears in the stream if necessary, if nothing
107     // ever does (i.e. EOF) LastRead() will return 0 (and the return value is
108     // undefined), otherwise 1
109     virtual char Peek();
110 
111     // return one byte from the stream, blocking until it appears if
112     // necessary
113     //
114     // on success returns a value between 0 - 255, or wxEOF on EOF or error.
115     int GetC();
116 
117     // read at most the given number of bytes from the stream
118     //
119     // there are 2 possible situations here: either there is nothing at all in
120     // the stream right now in which case Read() blocks until something appears
121     // (use CanRead() to avoid this) or there is already some data available in
122     // the stream and then Read() doesn't block but returns just the data it
123     // can read without waiting for more
124     //
125     // in any case, if there are not enough bytes in the stream right now,
126     // LastRead() value will be less than size but greater than 0. If it is 0,
127     // it means that EOF has been reached.
128     virtual wxInputStream& Read(void *buffer, size_t size);
129 
130     // copy the entire contents of this stream into streamOut, stopping only
131     // when EOF is reached or an error occurs
132     wxInputStream& Read(wxOutputStream& streamOut);
133 
134 
135     // status functions
136     // ----------------
137 
138     // returns the number of bytes read by the last call to Read(), GetC() or
139     // Peek()
140     //
141     // this should be used to discover whether that call succeeded in reading
142     // all the requested data or not
LastRead()143     virtual size_t LastRead() const { return wxStreamBase::m_lastcount; }
144 
145     // returns true if some data is available in the stream right now, so that
146     // calling Read() wouldn't block
147     virtual bool CanRead() const;
148 
149     // is the stream at EOF?
150     //
151     // note that this cannot be really implemented for all streams and
152     // CanRead() is more reliable than Eof()
153     virtual bool Eof() const;
154 
155 
156     // write back buffer
157     // -----------------
158 
159     // put back the specified number of bytes into the stream, they will be
160     // fetched by the next call to the read functions
161     //
162     // returns the number of bytes really stuffed back
163     size_t Ungetch(const void *buffer, size_t size);
164 
165     // put back the specified character in the stream
166     //
167     // returns true if ok, false on error
168     bool Ungetch(char c);
169 
170 
171     // position functions
172     // ------------------
173 
174     // move the stream pointer to the given position (if the stream supports
175     // it)
176     //
177     // returns wxInvalidOffset on error
178     virtual wxFileOffset SeekI(wxFileOffset pos, wxSeekMode mode = wxFromStart);
179 
180     // return the current position of the stream pointer or wxInvalidOffset
181     virtual wxFileOffset TellI() const;
182 
183 
184     // stream-like operators
185     // ---------------------
186 
187     wxInputStream& operator>>(wxOutputStream& out) { return Read(out); }
188     wxInputStream& operator>>(__wxInputManip func) { return func(*this); }
189 
190 protected:
191     // do read up to size bytes of data into the provided buffer
192     //
193     // this method should return 0 if EOF has been reached or an error occurred
194     // (m_lasterror should be set accordingly as well) or the number of bytes
195     // read
196     virtual size_t OnSysRead(void *buffer, size_t size) = 0;
197 
198     // write-back buffer support
199     // -------------------------
200 
201     // return the pointer to a buffer big enough to hold sizeNeeded bytes
202     char *AllocSpaceWBack(size_t sizeNeeded);
203 
204     // read up to size data from the write back buffer, return the number of
205     // bytes read
206     size_t GetWBack(void *buf, size_t size);
207 
208     // write back buffer or NULL if none
209     char *m_wback;
210 
211     // the size of the buffer
212     size_t m_wbacksize;
213 
214     // the current position in the buffer
215     size_t m_wbackcur;
216 
217     friend class wxStreamBuffer;
218 
219     DECLARE_NO_COPY_CLASS(wxInputStream)
220 };
221 
222 // ----------------------------------------------------------------------------
223 // wxOutputStream: base for the output streams
224 // ----------------------------------------------------------------------------
225 
226 class WXDLLIMPEXP_BASE wxOutputStream : public wxStreamBase
227 {
228 public:
229     wxOutputStream();
230     virtual ~wxOutputStream();
231 
232     void PutC(char c);
233     virtual wxOutputStream& Write(const void *buffer, size_t size);
234     wxOutputStream& Write(wxInputStream& stream_in);
235 
236     virtual wxFileOffset SeekO(wxFileOffset pos, wxSeekMode mode = wxFromStart);
237     virtual wxFileOffset TellO() const;
238 
LastWrite()239     virtual size_t LastWrite() const { return wxStreamBase::m_lastcount; }
240 
241     virtual void Sync();
Close()242     virtual bool Close() { return true; }
243 
244     wxOutputStream& operator<<(wxInputStream& out) { return Write(out); }
245     wxOutputStream& operator<<( __wxOutputManip func) { return func(*this); }
246 
247 protected:
248     // to be implemented in the derived classes (it should have been pure
249     // virtual)
250     virtual size_t OnSysWrite(const void *buffer, size_t bufsize);
251 
252     friend class wxStreamBuffer;
253 
254     DECLARE_NO_COPY_CLASS(wxOutputStream)
255 };
256 
257 // ============================================================================
258 // helper stream classes
259 // ============================================================================
260 
261 // ---------------------------------------------------------------------------
262 // A stream for measuring streamed output
263 // ---------------------------------------------------------------------------
264 
265 class WXDLLIMPEXP_BASE wxCountingOutputStream : public wxOutputStream
266 {
267 public:
268     wxCountingOutputStream();
269 
270     wxFileOffset GetLength() const;
Ok()271     bool Ok() const { return IsOk(); }
IsOk()272     bool IsOk() const { return true; }
273 
274 protected:
275     virtual size_t OnSysWrite(const void *buffer, size_t size);
276     virtual wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
277     virtual wxFileOffset OnSysTell() const;
278 
279     size_t m_currentPos;
280 
281     DECLARE_NO_COPY_CLASS(wxCountingOutputStream)
282 };
283 
284 // ---------------------------------------------------------------------------
285 // "Filter" streams
286 // ---------------------------------------------------------------------------
287 
288 class WXDLLIMPEXP_BASE wxFilterInputStream : public wxInputStream
289 {
290 public:
291     wxFilterInputStream();
292     wxFilterInputStream(wxInputStream& stream);
293     wxFilterInputStream(wxInputStream *stream);
294     virtual ~wxFilterInputStream();
295 
Peek()296     char Peek() { return m_parent_i_stream->Peek(); }
297 
GetLength()298     wxFileOffset GetLength() const { return m_parent_i_stream->GetLength(); }
299 
GetFilterInputStream()300     wxInputStream *GetFilterInputStream() const { return m_parent_i_stream; }
301 
302 protected:
303     wxInputStream *m_parent_i_stream;
304     bool m_owns;
305 
306     DECLARE_NO_COPY_CLASS(wxFilterInputStream)
307 };
308 
309 class WXDLLIMPEXP_BASE wxFilterOutputStream : public wxOutputStream
310 {
311 public:
312     wxFilterOutputStream();
313     wxFilterOutputStream(wxOutputStream& stream);
314     wxFilterOutputStream(wxOutputStream *stream);
315     virtual ~wxFilterOutputStream();
316 
GetLength()317     wxFileOffset GetLength() const { return m_parent_o_stream->GetLength(); }
318 
GetFilterOutputStream()319     wxOutputStream *GetFilterOutputStream() const { return m_parent_o_stream; }
320 
321     bool Close();
322 
323 protected:
324     wxOutputStream *m_parent_o_stream;
325     bool m_owns;
326 
327     DECLARE_NO_COPY_CLASS(wxFilterOutputStream)
328 };
329 
330 enum wxStreamProtocolType
331 {
332     wxSTREAM_PROTOCOL,  // wxFileSystem protocol (should be only one)
333     wxSTREAM_MIMETYPE,  // MIME types the stream handles
334     wxSTREAM_ENCODING,  // The HTTP Content-Encodings the stream handles
335     wxSTREAM_FILEEXT    // File extensions the stream handles
336 };
337 
338 void WXDLLIMPEXP_BASE wxUseFilterClasses();
339 
340 class WXDLLIMPEXP_BASE wxFilterClassFactoryBase : public wxObject
341 {
342 public:
~wxFilterClassFactoryBase()343     virtual ~wxFilterClassFactoryBase() { }
344 
GetProtocol()345     wxString GetProtocol() const { return wxString(*GetProtocols()); }
346     wxString PopExtension(const wxString& location) const;
347 
348     virtual const wxChar * const *GetProtocols(wxStreamProtocolType type
349                                                = wxSTREAM_PROTOCOL) const = 0;
350 
351     bool CanHandle(const wxChar *protocol,
352                    wxStreamProtocolType type
353                    = wxSTREAM_PROTOCOL) const;
354 
355 protected:
356     wxString::size_type FindExtension(const wxChar *location) const;
357 
358     DECLARE_ABSTRACT_CLASS(wxFilterClassFactoryBase)
359 };
360 
361 class WXDLLIMPEXP_BASE wxFilterClassFactory : public wxFilterClassFactoryBase
362 {
363 public:
~wxFilterClassFactory()364     virtual ~wxFilterClassFactory() { }
365 
366     virtual wxFilterInputStream  *NewStream(wxInputStream& stream)  const = 0;
367     virtual wxFilterOutputStream *NewStream(wxOutputStream& stream) const = 0;
368     virtual wxFilterInputStream  *NewStream(wxInputStream *stream)  const = 0;
369     virtual wxFilterOutputStream *NewStream(wxOutputStream *stream) const = 0;
370 
371     static const wxFilterClassFactory *Find(const wxChar *protocol,
372                                             wxStreamProtocolType type
373                                             = wxSTREAM_PROTOCOL);
374 
375     static const wxFilterClassFactory *GetFirst();
GetNext()376     const wxFilterClassFactory *GetNext() const { return m_next; }
377 
PushFront()378     void PushFront() { Remove(); m_next = sm_first; sm_first = this; }
379     void Remove();
380 
381 protected:
wxFilterClassFactory()382     wxFilterClassFactory() : m_next(this) { }
383 
384     wxFilterClassFactory& operator=(const wxFilterClassFactory&)
385         { return *this; }
386 
387 private:
388     static wxFilterClassFactory *sm_first;
389     wxFilterClassFactory *m_next;
390 
391     DECLARE_ABSTRACT_CLASS(wxFilterClassFactory)
392 };
393 
394 // ============================================================================
395 // buffered streams
396 // ============================================================================
397 
398 // ---------------------------------------------------------------------------
399 // Stream buffer: this class can be derived from and passed to
400 // wxBufferedStreams to implement custom buffering
401 // ---------------------------------------------------------------------------
402 
403 class WXDLLIMPEXP_BASE wxStreamBuffer
404 {
405 public:
406     enum BufMode
407     {
408         read,
409         write,
410         read_write
411     };
412 
413     wxStreamBuffer(wxStreamBase& stream, BufMode mode);
414     wxStreamBuffer(const wxStreamBuffer& buf);
415     virtual ~wxStreamBuffer();
416 
417     // Filtered IO
418     virtual size_t Read(void *buffer, size_t size);
419     size_t Read(wxStreamBuffer *buf);
420     virtual size_t Write(const void *buffer, size_t size);
421     size_t Write(wxStreamBuffer *buf);
422 
423     virtual char Peek();
424     virtual char GetChar();
425     virtual void PutChar(char c);
426     virtual wxFileOffset Tell() const;
427     virtual wxFileOffset Seek(wxFileOffset pos, wxSeekMode mode);
428 
429     // Buffer control
430     void ResetBuffer();
431 
432     // NB: the buffer must always be allocated with malloc() if takeOwn is
433     //     true as it will be deallocated by free()
434     void SetBufferIO(void *start, void *end, bool takeOwnership = false);
435     void SetBufferIO(void *start, size_t len, bool takeOwnership = false);
436     void SetBufferIO(size_t bufsize);
GetBufferStart()437     void *GetBufferStart() const { return m_buffer_start; }
GetBufferEnd()438     void *GetBufferEnd() const { return m_buffer_end; }
GetBufferPos()439     void *GetBufferPos() const { return m_buffer_pos; }
GetBufferSize()440     size_t GetBufferSize() const { return m_buffer_size; }
GetIntPosition()441     size_t GetIntPosition() const { return m_buffer_pos - m_buffer_start; }
SetIntPosition(size_t pos)442     void SetIntPosition(size_t pos) { m_buffer_pos = m_buffer_start + pos; }
GetLastAccess()443     size_t GetLastAccess() const { return m_buffer_end - m_buffer_start; }
GetBytesLeft()444     size_t GetBytesLeft() const { return m_buffer_end - m_buffer_pos; }
445 
Fixed(bool fixed)446     void Fixed(bool fixed) { m_fixed = fixed; }
Flushable(bool f)447     void Flushable(bool f) { m_flushable = f; }
448 
449     bool FlushBuffer();
450     bool FillBuffer();
451     size_t GetDataLeft();
452 
453     // misc accessors
GetStream()454     wxStreamBase *GetStream() const { return m_stream; }
HasBuffer()455     bool HasBuffer() const { return m_buffer_size != 0; }
456 
IsFixed()457     bool IsFixed() const { return m_fixed; }
IsFlushable()458     bool IsFlushable() const { return m_flushable; }
459 
460     // only for input/output buffers respectively, returns NULL otherwise
461     wxInputStream *GetInputStream() const;
462     wxOutputStream *GetOutputStream() const;
463 
464 #if WXWIN_COMPATIBILITY_2_6
465     // deprecated, for compatibility only
466     wxDEPRECATED( wxStreamBase *Stream() );
467 #endif // WXWIN_COMPATIBILITY_2_6
468 
469     // this constructs a dummy wxStreamBuffer, used by (and exists for)
470     // wxMemoryStreams only, don't use!
471     wxStreamBuffer(BufMode mode);
472 
473 protected:
474     void GetFromBuffer(void *buffer, size_t size);
475     void PutToBuffer(const void *buffer, size_t size);
476 
477     // set the last error to the specified value if we didn't have it before
478     void SetError(wxStreamError err);
479 
480     // common part of several ctors
481     void Init();
482 
483     // init buffer variables to be empty
484     void InitBuffer();
485 
486     // free the buffer (always safe to call)
487     void FreeBuffer();
488 
489     // the buffer itself: the pointers to its start and end and the current
490     // position in the buffer
491     char *m_buffer_start,
492          *m_buffer_end,
493          *m_buffer_pos;
494 
495     // the buffer size
496     // FIXME: isn't it the same as m_buffer_end - m_buffer_start? (VZ)
497     size_t m_buffer_size;
498 
499     // the stream we're associated with
500     wxStreamBase *m_stream;
501 
502     // its mode
503     BufMode m_mode;
504 
505     // flags
506     bool m_destroybuf,      // deallocate buffer?
507          m_fixed,
508          m_flushable;
509 
510 private:
511 // Cannot use
512 //  DECLARE_NO_COPY_CLASS(wxStreamBuffer)
513 // because copy constructor is explicitly declared above;
514 // but no copy assignment operator is defined, so declare
515 // it private to prevent the compiler from defining it:
516     wxStreamBuffer& operator=(const wxStreamBuffer&);
517 };
518 
519 // ---------------------------------------------------------------------------
520 // wxBufferedInputStream
521 // ---------------------------------------------------------------------------
522 
523 class WXDLLIMPEXP_BASE wxBufferedInputStream : public wxFilterInputStream
524 {
525 public:
526     // if a non NULL buffer is given to the stream, it will be deleted by it
527     wxBufferedInputStream(wxInputStream& stream,
528                           wxStreamBuffer *buffer = NULL);
529     virtual ~wxBufferedInputStream();
530 
531     char Peek();
532     wxInputStream& Read(void *buffer, size_t size);
533 
534     // Position functions
535     wxFileOffset SeekI(wxFileOffset pos, wxSeekMode mode = wxFromStart);
536     wxFileOffset TellI() const;
IsSeekable()537     bool IsSeekable() const { return m_parent_i_stream->IsSeekable(); }
538 
539     // the buffer given to the stream will be deleted by it
540     void SetInputStreamBuffer(wxStreamBuffer *buffer);
GetInputStreamBuffer()541     wxStreamBuffer *GetInputStreamBuffer() const { return m_i_streambuf; }
542 
543 #if WXWIN_COMPATIBILITY_2_6
544     // deprecated, for compatibility only
545     wxDEPRECATED( wxStreamBuffer *InputStreamBuffer() const );
546 #endif // WXWIN_COMPATIBILITY_2_6
547 
548 protected:
549     virtual size_t OnSysRead(void *buffer, size_t bufsize);
550     virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
551     virtual wxFileOffset OnSysTell() const;
552 
553     wxStreamBuffer *m_i_streambuf;
554 
555     DECLARE_NO_COPY_CLASS(wxBufferedInputStream)
556 };
557 
558 // ----------------------------------------------------------------------------
559 // wxBufferedOutputStream
560 // ----------------------------------------------------------------------------
561 
562 class WXDLLIMPEXP_BASE wxBufferedOutputStream : public wxFilterOutputStream
563 {
564 public:
565     // if a non NULL buffer is given to the stream, it will be deleted by it
566     wxBufferedOutputStream(wxOutputStream& stream,
567                            wxStreamBuffer *buffer = NULL);
568     virtual ~wxBufferedOutputStream();
569 
570     wxOutputStream& Write(const void *buffer, size_t size);
571 
572     // Position functions
573     wxFileOffset SeekO(wxFileOffset pos, wxSeekMode mode = wxFromStart);
574     wxFileOffset TellO() const;
IsSeekable()575     bool IsSeekable() const { return m_parent_o_stream->IsSeekable(); }
576 
577     void Sync();
578     bool Close();
579 
580     wxFileOffset GetLength() const;
581 
582     // the buffer given to the stream will be deleted by it
583     void SetOutputStreamBuffer(wxStreamBuffer *buffer);
GetOutputStreamBuffer()584     wxStreamBuffer *GetOutputStreamBuffer() const { return m_o_streambuf; }
585 
586 #if WXWIN_COMPATIBILITY_2_6
587     // deprecated, for compatibility only
588     wxDEPRECATED( wxStreamBuffer *OutputStreamBuffer() const );
589 #endif // WXWIN_COMPATIBILITY_2_6
590 
591 protected:
592     virtual size_t OnSysWrite(const void *buffer, size_t bufsize);
593     virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
594     virtual wxFileOffset OnSysTell() const;
595 
596     wxStreamBuffer *m_o_streambuf;
597 
598     DECLARE_NO_COPY_CLASS(wxBufferedOutputStream)
599 };
600 
601 #if WXWIN_COMPATIBILITY_2_6
Stream()602     inline wxStreamBase *wxStreamBuffer::Stream() { return m_stream; }
InputStreamBuffer()603     inline wxStreamBuffer *wxBufferedInputStream::InputStreamBuffer() const { return m_i_streambuf; }
OutputStreamBuffer()604     inline wxStreamBuffer *wxBufferedOutputStream::OutputStreamBuffer() const { return m_o_streambuf; }
605 #endif // WXWIN_COMPATIBILITY_2_6
606 
607 #endif // wxUSE_STREAMS
608 
609 #endif // _WX_WXSTREAM_H__
610