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