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