Coverage Report

Created: 2025-11-16 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wxwidgets/include/wx/stream.h
Line
Count
Source
1
/////////////////////////////////////////////////////////////////////////////
2
// Name:        wx/stream.h
3
// Purpose:     stream classes
4
// Author:      Guilhem Lavaux, Guillermo Rodriguez Garcia, Vadim Zeitlin
5
// Created:     11/07/98
6
// Copyright:   (c) Guilhem Lavaux
7
// Licence:     wxWindows licence
8
/////////////////////////////////////////////////////////////////////////////
9
10
#ifndef _WX_WXSTREAM_H__
11
#define _WX_WXSTREAM_H__
12
13
#include "wx/defs.h"
14
15
#if wxUSE_STREAMS
16
17
#include "wx/object.h"
18
#include "wx/string.h"
19
#include "wx/filefn.h"  // for wxFileOffset, wxInvalidOffset and wxSeekMode
20
21
class WXDLLIMPEXP_FWD_BASE wxStreamBase;
22
class WXDLLIMPEXP_FWD_BASE wxInputStream;
23
class WXDLLIMPEXP_FWD_BASE wxOutputStream;
24
25
typedef wxInputStream& (*__wxInputManip)(wxInputStream&);
26
typedef wxOutputStream& (*__wxOutputManip)(wxOutputStream&);
27
28
WXDLLIMPEXP_BASE wxOutputStream& wxEndL(wxOutputStream& o_stream);
29
30
// ----------------------------------------------------------------------------
31
// constants
32
// ----------------------------------------------------------------------------
33
34
enum wxStreamError
35
{
36
    wxSTREAM_NO_ERROR = 0,      // stream is in good state
37
    wxSTREAM_EOF,               // EOF reached in Read() or similar
38
    wxSTREAM_WRITE_ERROR,       // generic write error
39
    wxSTREAM_READ_ERROR         // generic read error
40
};
41
42
const int wxEOF = -1;
43
44
// ============================================================================
45
// base stream classes: wxInputStream and wxOutputStream
46
// ============================================================================
47
48
// ---------------------------------------------------------------------------
49
// wxStreamBase: common (but non virtual!) base for all stream classes
50
// ---------------------------------------------------------------------------
51
52
class WXDLLIMPEXP_BASE wxStreamBase : public wxObject
53
{
54
public:
55
    wxStreamBase();
56
    virtual ~wxStreamBase();
57
58
    // error testing
59
36.2k
    wxStreamError GetLastError() const { return m_lasterror; }
60
33.6k
    virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; }
61
0
    bool operator!() const { return !IsOk(); }
62
63
    // reset the stream state
64
0
    void Reset(wxStreamError error = wxSTREAM_NO_ERROR) { m_lasterror = error; }
65
66
    // this doesn't make sense for all streams, always test its return value
67
    virtual size_t GetSize() const;
68
0
    virtual wxFileOffset GetLength() const { return wxInvalidOffset; }
69
70
    // returns true if the streams supports seeking to arbitrary offsets
71
0
    virtual bool IsSeekable() const { return false; }
72
73
protected:
74
    virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
75
    virtual wxFileOffset OnSysTell() const;
76
77
    size_t m_lastcount;
78
    wxStreamError m_lasterror;
79
80
    friend class wxStreamBuffer;
81
82
    wxDECLARE_ABSTRACT_CLASS(wxStreamBase);
83
    wxDECLARE_NO_COPY_CLASS(wxStreamBase);
84
};
85
86
// ----------------------------------------------------------------------------
87
// wxInputStream: base class for the input streams
88
// ----------------------------------------------------------------------------
89
90
class WXDLLIMPEXP_BASE wxInputStream : public wxStreamBase
91
{
92
public:
93
    // ctor and dtor, nothing exciting
94
    wxInputStream();
95
    virtual ~wxInputStream();
96
97
98
    // IO functions
99
    // ------------
100
101
    // return a character from the stream without removing it, i.e. it will
102
    // still be returned by the next call to GetC()
103
    //
104
    // blocks until something appears in the stream if necessary, if nothing
105
    // ever does (i.e. EOF) LastRead() will return 0 (and the return value is
106
    // undefined), otherwise 1
107
    virtual char Peek();
108
109
    // return one byte from the stream, blocking until it appears if
110
    // necessary
111
    //
112
    // on success returns a value between 0 - 255, or wxEOF on EOF or error.
113
    int GetC();
114
115
    // read at most the given number of bytes from the stream
116
    //
117
    // there are 2 possible situations here: either there is nothing at all in
118
    // the stream right now in which case Read() blocks until something appears
119
    // (use CanRead() to avoid this) or there is already some data available in
120
    // the stream and then Read() doesn't block but returns just the data it
121
    // can read without waiting for more
122
    //
123
    // in any case, if there are not enough bytes in the stream right now,
124
    // LastRead() value will be less than size but greater than 0. If it is 0,
125
    // it means that EOF has been reached.
126
    virtual wxInputStream& Read(void *buffer, size_t size);
127
128
    // Read exactly the given number of bytes, unlike Read(), which may read
129
    // less than the requested amount of data without returning an error, this
130
    // method either reads all the data or returns false.
131
    bool ReadAll(void *buffer, size_t size);
132
133
    // copy the entire contents of this stream into streamOut, stopping only
134
    // when EOF is reached or an error occurs
135
    wxInputStream& Read(wxOutputStream& streamOut);
136
137
138
    // status functions
139
    // ----------------
140
141
    // returns the number of bytes read by the last call to Read(), GetC() or
142
    // Peek()
143
    //
144
    // this should be used to discover whether that call succeeded in reading
145
    // all the requested data or not
146
99.9k
    virtual size_t LastRead() const { return wxStreamBase::m_lastcount; }
147
148
    // returns true if some data is available in the stream right now, so that
149
    // calling Read() wouldn't block
150
    virtual bool CanRead() const;
151
152
    // is the stream at EOF?
153
    //
154
    // note that this cannot be really implemented for all streams and
155
    // CanRead() is more reliable than Eof()
156
    virtual bool Eof() const;
157
158
159
    // write back buffer
160
    // -----------------
161
162
    // put back the specified number of bytes into the stream, they will be
163
    // fetched by the next call to the read functions
164
    //
165
    // returns the number of bytes really stuffed back
166
    size_t Ungetch(const void *buffer, size_t size);
167
168
    // put back the specified character in the stream
169
    //
170
    // returns true if ok, false on error
171
    bool Ungetch(char c);
172
173
174
    // position functions
175
    // ------------------
176
177
    // move the stream pointer to the given position (if the stream supports
178
    // it)
179
    //
180
    // returns wxInvalidOffset on error
181
    virtual wxFileOffset SeekI(wxFileOffset pos, wxSeekMode mode = wxFromStart);
182
183
    // return the current position of the stream pointer or wxInvalidOffset
184
    virtual wxFileOffset TellI() const;
185
186
187
    // stream-like operators
188
    // ---------------------
189
190
0
    wxInputStream& operator>>(wxOutputStream& out) { return Read(out); }
191
0
    wxInputStream& operator>>(__wxInputManip func) { return func(*this); }
192
193
protected:
194
    // do read up to size bytes of data into the provided buffer
195
    //
196
    // this method should return 0 if EOF has been reached or an error occurred
197
    // (m_lasterror should be set accordingly as well) or the number of bytes
198
    // read
199
    virtual size_t OnSysRead(void *buffer, size_t size) = 0;
200
201
    // write-back buffer support
202
    // -------------------------
203
204
    // return the pointer to a buffer big enough to hold sizeNeeded bytes
205
    char *AllocSpaceWBack(size_t sizeNeeded);
206
207
    // read up to size data from the write back buffer, return the number of
208
    // bytes read
209
    size_t GetWBack(void *buf, size_t size);
210
211
    // write back buffer or nullptr if none
212
    char *m_wback;
213
214
    // the size of the buffer
215
    size_t m_wbacksize;
216
217
    // the current position in the buffer
218
    size_t m_wbackcur;
219
220
    friend class wxStreamBuffer;
221
222
    wxDECLARE_ABSTRACT_CLASS(wxInputStream);
223
    wxDECLARE_NO_COPY_CLASS(wxInputStream);
224
};
225
226
// ----------------------------------------------------------------------------
227
// wxOutputStream: base for the output streams
228
// ----------------------------------------------------------------------------
229
230
class WXDLLIMPEXP_BASE wxOutputStream : public wxStreamBase
231
{
232
public:
233
    wxOutputStream();
234
    virtual ~wxOutputStream();
235
236
    void PutC(char c);
237
    virtual wxOutputStream& Write(const void *buffer, size_t size);
238
239
    // This is ReadAll() equivalent for Write(): it either writes exactly the
240
    // given number of bytes or returns false, unlike Write() which can write
241
    // less data than requested but still return without error.
242
    bool WriteAll(const void *buffer, size_t size);
243
244
    wxOutputStream& Write(wxInputStream& stream_in);
245
246
    virtual wxFileOffset SeekO(wxFileOffset pos, wxSeekMode mode = wxFromStart);
247
    virtual wxFileOffset TellO() const;
248
249
0
    virtual size_t LastWrite() const { return wxStreamBase::m_lastcount; }
250
251
    virtual void Sync();
252
0
    virtual bool Close() { return true; }
253
254
0
    wxOutputStream& operator<<(wxInputStream& out) { return Write(out); }
255
0
    wxOutputStream& operator<<( __wxOutputManip func) { return func(*this); }
256
257
protected:
258
    // to be implemented in the derived classes (it should have been pure
259
    // virtual)
260
    virtual size_t OnSysWrite(const void *buffer, size_t bufsize);
261
262
    friend class wxStreamBuffer;
263
264
    wxDECLARE_ABSTRACT_CLASS(wxOutputStream);
265
    wxDECLARE_NO_COPY_CLASS(wxOutputStream);
266
};
267
268
// ============================================================================
269
// helper stream classes
270
// ============================================================================
271
272
// ---------------------------------------------------------------------------
273
// A stream for measuring streamed output
274
// ---------------------------------------------------------------------------
275
276
class WXDLLIMPEXP_BASE wxCountingOutputStream : public wxOutputStream
277
{
278
public:
279
    wxCountingOutputStream();
280
281
    virtual wxFileOffset GetLength() const override;
282
0
    bool Ok() const { return IsOk(); }
283
0
    virtual bool IsOk() const override { return true; }
284
285
protected:
286
    virtual size_t OnSysWrite(const void *buffer, size_t size) override;
287
    virtual wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode) override;
288
    virtual wxFileOffset OnSysTell() const override;
289
290
    size_t m_currentPos,
291
           m_lastPos;
292
293
    wxDECLARE_DYNAMIC_CLASS(wxCountingOutputStream);
294
    wxDECLARE_NO_COPY_CLASS(wxCountingOutputStream);
295
};
296
297
// ---------------------------------------------------------------------------
298
// "Filter" streams
299
// ---------------------------------------------------------------------------
300
301
class WXDLLIMPEXP_BASE wxFilterInputStream : public wxInputStream
302
{
303
public:
304
    wxFilterInputStream();
305
    wxFilterInputStream(wxInputStream& stream);
306
    wxFilterInputStream(wxInputStream *stream);
307
    virtual ~wxFilterInputStream();
308
309
0
    virtual char Peek() override { return m_parent_i_stream->Peek(); }
310
311
0
    virtual wxFileOffset GetLength() const override { return m_parent_i_stream->GetLength(); }
312
313
0
    wxInputStream *GetFilterInputStream() const { return m_parent_i_stream; }
314
315
protected:
316
    wxInputStream *m_parent_i_stream;
317
    bool m_owns;
318
319
    wxDECLARE_ABSTRACT_CLASS(wxFilterInputStream);
320
    wxDECLARE_NO_COPY_CLASS(wxFilterInputStream);
321
};
322
323
class WXDLLIMPEXP_BASE wxFilterOutputStream : public wxOutputStream
324
{
325
public:
326
    wxFilterOutputStream();
327
    wxFilterOutputStream(wxOutputStream& stream);
328
    wxFilterOutputStream(wxOutputStream *stream);
329
    virtual ~wxFilterOutputStream();
330
331
0
    virtual wxFileOffset GetLength() const override { return m_parent_o_stream->GetLength(); }
332
333
0
    wxOutputStream *GetFilterOutputStream() const { return m_parent_o_stream; }
334
335
    bool Close() override;
336
337
protected:
338
    wxOutputStream *m_parent_o_stream;
339
    bool m_owns;
340
341
    wxDECLARE_ABSTRACT_CLASS(wxFilterOutputStream);
342
    wxDECLARE_NO_COPY_CLASS(wxFilterOutputStream);
343
};
344
345
enum wxStreamProtocolType
346
{
347
    wxSTREAM_PROTOCOL,  // wxFileSystem protocol (should be only one)
348
    wxSTREAM_MIMETYPE,  // MIME types the stream handles
349
    wxSTREAM_ENCODING,  // The HTTP Content-Encodings the stream handles
350
    wxSTREAM_FILEEXT    // File extensions the stream handles
351
};
352
353
void WXDLLIMPEXP_BASE wxUseFilterClasses();
354
355
class WXDLLIMPEXP_BASE wxFilterClassFactoryBase : public wxObject
356
{
357
public:
358
    virtual ~wxFilterClassFactoryBase() = default;
359
360
0
    wxString GetProtocol() const { return wxString(*GetProtocols()); }
361
    wxString PopExtension(const wxString& location) const;
362
363
    virtual const wxChar * const *GetProtocols(wxStreamProtocolType type
364
                                               = wxSTREAM_PROTOCOL) const = 0;
365
366
    bool CanHandle(const wxString& protocol,
367
                   wxStreamProtocolType type
368
                   = wxSTREAM_PROTOCOL) const;
369
370
protected:
371
    wxString::size_type FindExtension(const wxString& location) const;
372
373
    wxDECLARE_ABSTRACT_CLASS(wxFilterClassFactoryBase);
374
};
375
376
class WXDLLIMPEXP_BASE wxFilterClassFactory : public wxFilterClassFactoryBase
377
{
378
public:
379
    virtual ~wxFilterClassFactory() = default;
380
381
    virtual wxFilterInputStream  *NewStream(wxInputStream& stream)  const = 0;
382
    virtual wxFilterOutputStream *NewStream(wxOutputStream& stream) const = 0;
383
    virtual wxFilterInputStream  *NewStream(wxInputStream *stream)  const = 0;
384
    virtual wxFilterOutputStream *NewStream(wxOutputStream *stream) const = 0;
385
386
    static const wxFilterClassFactory *Find(const wxString& protocol,
387
                                            wxStreamProtocolType type
388
                                            = wxSTREAM_PROTOCOL);
389
390
    static const wxFilterClassFactory *GetFirst();
391
0
    const wxFilterClassFactory *GetNext() const { return m_next; }
392
393
4
    void PushFront() { Remove(); m_next = sm_first; sm_first = this; }
394
    void Remove();
395
396
protected:
397
4
    wxFilterClassFactory() : m_next(this) { }
398
399
    wxFilterClassFactory& operator=(const wxFilterClassFactory&)
400
0
        { return *this; }
401
402
private:
403
    static wxFilterClassFactory *sm_first;
404
    wxFilterClassFactory *m_next;
405
406
    wxDECLARE_ABSTRACT_CLASS(wxFilterClassFactory);
407
};
408
409
// ============================================================================
410
// buffered streams
411
// ============================================================================
412
413
// ---------------------------------------------------------------------------
414
// Stream buffer: this class can be derived from and passed to
415
// wxBufferedStreams to implement custom buffering
416
// ---------------------------------------------------------------------------
417
418
class WXDLLIMPEXP_BASE wxStreamBuffer
419
{
420
public:
421
    // suppress Xcode 11 warning about shadowing global read() symbol
422
    wxCLANG_WARNING_SUPPRESS(shadow)
423
424
    enum BufMode
425
    {
426
        read,
427
        write,
428
        read_write
429
    };
430
431
    wxCLANG_WARNING_RESTORE(shadow)
432
433
    wxStreamBuffer(wxStreamBase& stream, BufMode mode)
434
0
    {
435
0
        InitWithStream(stream, mode);
436
0
    }
437
438
    wxStreamBuffer(size_t bufsize, wxInputStream& stream)
439
0
    {
440
0
        InitWithStream(stream, read);
441
0
        SetBufferIO(bufsize);
442
0
    }
443
444
    wxStreamBuffer(size_t bufsize, wxOutputStream& stream)
445
0
    {
446
0
        InitWithStream(stream, write);
447
0
        SetBufferIO(bufsize);
448
0
    }
449
450
    wxStreamBuffer(const wxStreamBuffer& buf);
451
    virtual ~wxStreamBuffer();
452
453
    // Filtered IO
454
    virtual size_t Read(void *buffer, size_t size);
455
    size_t Read(wxStreamBuffer *buf);
456
    virtual size_t Write(const void *buffer, size_t size);
457
    size_t Write(wxStreamBuffer *buf);
458
459
    virtual char Peek();
460
    virtual char GetChar();
461
    virtual void PutChar(char c);
462
    virtual wxFileOffset Tell() const;
463
    virtual wxFileOffset Seek(wxFileOffset pos, wxSeekMode mode);
464
465
    // Buffer control
466
    void ResetBuffer();
467
    void Truncate();
468
469
    // NB: the buffer must always be allocated with malloc() if takeOwn is
470
    //     true as it will be deallocated by free()
471
    void SetBufferIO(void *start, void *end, bool takeOwnership = false);
472
    void SetBufferIO(void *start, size_t len, bool takeOwnership = false);
473
    void SetBufferIO(size_t bufsize);
474
0
    void *GetBufferStart() const { return m_buffer_start; }
475
0
    void *GetBufferEnd() const { return m_buffer_end; }
476
0
    void *GetBufferPos() const { return m_buffer_pos; }
477
0
    size_t GetBufferSize() const { return m_buffer_end - m_buffer_start; }
478
242k
    size_t GetIntPosition() const { return m_buffer_pos - m_buffer_start; }
479
36.0k
    void SetIntPosition(size_t pos) { m_buffer_pos = m_buffer_start + pos; }
480
37.1k
    size_t GetLastAccess() const { return m_buffer_end - m_buffer_start; }
481
193k
    size_t GetBytesLeft() const { return m_buffer_end - m_buffer_pos; }
482
483
2.61k
    void Fixed(bool fixed) { m_fixed = fixed; }
484
0
    void Flushable(bool f) { m_flushable = f; }
485
486
    bool FlushBuffer();
487
    bool FillBuffer();
488
    size_t GetDataLeft();
489
490
    // misc accessors
491
0
    wxStreamBase *GetStream() const { return m_stream; }
492
96.5k
    bool HasBuffer() const { return m_buffer_start != m_buffer_end; }
493
494
0
    bool IsFixed() const { return m_fixed; }
495
0
    bool IsFlushable() const { return m_flushable; }
496
497
    // only for input/output buffers respectively, returns nullptr otherwise
498
    wxInputStream *GetInputStream() const;
499
    wxOutputStream *GetOutputStream() const;
500
501
    // this constructs a dummy wxStreamBuffer, used by (and exists for)
502
    // wxMemoryStreams only, don't use!
503
    wxStreamBuffer(BufMode mode);
504
505
protected:
506
    void GetFromBuffer(void *buffer, size_t size);
507
    void PutToBuffer(const void *buffer, size_t size);
508
509
    // set the last error to the specified value if we didn't have it before
510
    void SetError(wxStreamError err);
511
512
    // common part of several ctors
513
    void Init();
514
515
    // common part of ctors taking wxStreamBase parameter
516
    void InitWithStream(wxStreamBase& stream, BufMode mode);
517
518
    // init buffer variables to be empty
519
    void InitBuffer();
520
521
    // free the buffer (always safe to call)
522
    void FreeBuffer();
523
524
    // the buffer itself: the pointers to its start and end and the current
525
    // position in the buffer
526
    char *m_buffer_start,
527
         *m_buffer_end,
528
         *m_buffer_pos;
529
530
    // the stream we're associated with
531
    wxStreamBase *m_stream;
532
533
    // its mode
534
    BufMode m_mode;
535
536
    // flags
537
    bool m_destroybuf,      // deallocate buffer?
538
         m_fixed,
539
         m_flushable;
540
541
542
    wxDECLARE_NO_ASSIGN_CLASS(wxStreamBuffer);
543
};
544
545
// ---------------------------------------------------------------------------
546
// wxBufferedInputStream
547
// ---------------------------------------------------------------------------
548
549
class WXDLLIMPEXP_BASE wxBufferedInputStream : public wxFilterInputStream
550
{
551
public:
552
    // create a buffered stream on top of the specified low-level stream
553
    //
554
    // if a non null buffer is given to the stream, it will be deleted by it,
555
    // otherwise a default 1KB buffer will be used
556
    wxBufferedInputStream(wxInputStream& stream,
557
                          wxStreamBuffer *buffer = nullptr);
558
559
    // ctor allowing to specify the buffer size, it's just a more convenient
560
    // alternative to creating wxStreamBuffer, calling its SetBufferIO(bufsize)
561
    // and using the ctor above
562
    wxBufferedInputStream(wxInputStream& stream, size_t bufsize);
563
564
565
    virtual ~wxBufferedInputStream();
566
567
    virtual char Peek() override;
568
    virtual wxInputStream& Read(void *buffer, size_t size) override;
569
570
    // Position functions
571
    virtual wxFileOffset SeekI(wxFileOffset pos, wxSeekMode mode = wxFromStart) override;
572
    virtual wxFileOffset TellI() const override;
573
0
    virtual bool IsSeekable() const override { return m_parent_i_stream->IsSeekable(); }
574
575
    // the buffer given to the stream will be deleted by it
576
    void SetInputStreamBuffer(wxStreamBuffer *buffer);
577
0
    wxStreamBuffer *GetInputStreamBuffer() const { return m_i_streambuf; }
578
579
protected:
580
    virtual size_t OnSysRead(void *buffer, size_t bufsize) override;
581
    virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) override;
582
    virtual wxFileOffset OnSysTell() const override;
583
584
    wxStreamBuffer *m_i_streambuf;
585
586
    wxDECLARE_NO_COPY_CLASS(wxBufferedInputStream);
587
};
588
589
// ----------------------------------------------------------------------------
590
// wxBufferedOutputStream
591
// ----------------------------------------------------------------------------
592
593
class WXDLLIMPEXP_BASE wxBufferedOutputStream : public wxFilterOutputStream
594
{
595
public:
596
    // create a buffered stream on top of the specified low-level stream
597
    //
598
    // if a non null buffer is given to the stream, it will be deleted by it,
599
    // otherwise a default 1KB buffer will be used
600
    wxBufferedOutputStream(wxOutputStream& stream,
601
                           wxStreamBuffer *buffer = nullptr);
602
603
    // ctor allowing to specify the buffer size, it's just a more convenient
604
    // alternative to creating wxStreamBuffer, calling its SetBufferIO(bufsize)
605
    // and using the ctor above
606
    wxBufferedOutputStream(wxOutputStream& stream, size_t bufsize);
607
608
    virtual ~wxBufferedOutputStream();
609
610
    virtual wxOutputStream& Write(const void *buffer, size_t size) override;
611
612
    // Position functions
613
    virtual wxFileOffset SeekO(wxFileOffset pos, wxSeekMode mode = wxFromStart) override;
614
    virtual wxFileOffset TellO() const override;
615
0
    virtual bool IsSeekable() const override { return m_parent_o_stream->IsSeekable(); }
616
617
    void Sync() override;
618
    bool Close() override;
619
620
    virtual wxFileOffset GetLength() const override;
621
622
    // the buffer given to the stream will be deleted by it
623
    void SetOutputStreamBuffer(wxStreamBuffer *buffer);
624
0
    wxStreamBuffer *GetOutputStreamBuffer() const { return m_o_streambuf; }
625
626
protected:
627
    virtual size_t OnSysWrite(const void *buffer, size_t bufsize) override;
628
    virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) override;
629
    virtual wxFileOffset OnSysTell() const override;
630
631
    wxStreamBuffer *m_o_streambuf;
632
633
    wxDECLARE_NO_COPY_CLASS(wxBufferedOutputStream);
634
};
635
636
// ---------------------------------------------------------------------------
637
// wxWrapperInputStream: forwards all IO to another stream.
638
// ---------------------------------------------------------------------------
639
640
class WXDLLIMPEXP_BASE wxWrapperInputStream : public wxFilterInputStream
641
{
642
public:
643
    // Constructor fully initializing the stream. The overload taking pointer
644
    // takes ownership of the parent stream, the one taking reference does not.
645
    //
646
    // Notice that this class also has a default ctor but it's protected as the
647
    // derived class is supposed to take care of calling InitParentStream() if
648
    // it's used.
649
    wxWrapperInputStream(wxInputStream& stream);
650
    wxWrapperInputStream(wxInputStream* stream);
651
652
    // Override the base class methods to forward to the wrapped stream.
653
    virtual wxFileOffset GetLength() const override;
654
    virtual bool IsSeekable() const override;
655
656
protected:
657
    virtual size_t OnSysRead(void *buffer, size_t size) override;
658
    virtual wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode) override;
659
    virtual wxFileOffset OnSysTell() const override;
660
661
    // Ensure that our own last error is the same as that of the real stream.
662
    //
663
    // This method is const because the error must be updated even from const
664
    // methods (in other words, it really should have been mutable in the first
665
    // place).
666
    void SynchronizeLastError() const
667
0
    {
668
0
        const_cast<wxWrapperInputStream*>(this)->
669
0
            Reset(m_parent_i_stream->GetLastError());
670
0
    }
671
672
    // Default constructor, use InitParentStream() later.
673
    wxWrapperInputStream();
674
675
    // Set up the wrapped stream for an object initialized using the default
676
    // constructor. The ownership logic is the same as above.
677
    void InitParentStream(wxInputStream& stream);
678
    void InitParentStream(wxInputStream* stream);
679
680
    wxDECLARE_NO_COPY_CLASS(wxWrapperInputStream);
681
};
682
683
// ----------------------------------------------------------------------------
684
// wxPeekInputStream(): read some data from a stream and then rewind it back
685
// ----------------------------------------------------------------------------
686
687
// This semi-private class is used in wx code to read some data, using the
688
// provided method of the class T, from a stream if it's seekable and then
689
// rewind it back.
690
class wxInputStreamPeeker
691
{
692
public:
693
    explicit wxInputStreamPeeker(wxInputStream& stream)
694
        : m_stream(stream),
695
          m_ofsOrig(stream.IsSeekable() ? stream.TellI() : wxInvalidOffset)
696
0
    {
697
0
    }
698
699
    // Call the given function if the stream is seekable, otherwise return 0.
700
    template <typename R, typename T>
701
    R CallIfCanSeek(R (T::*func)(wxInputStream&), T* obj)
702
    {
703
        return RewindAndReturn(CanSeek() ? (obj->*func)(m_stream) : R(0));
704
    }
705
706
    // Overload for const methods.
707
    template <typename R, typename T>
708
    R CallIfCanSeek(R (T::*func)(wxInputStream&) const, const T* obj)
709
    {
710
        return RewindAndReturn(CanSeek() ? (obj->*func)(m_stream) : R(0));
711
    }
712
713
private:
714
0
    bool CanSeek() const { return m_ofsOrig != wxInvalidOffset; }
715
716
    template <typename R>
717
    R RewindAndReturn(R retval)
718
    {
719
        if ( CanSeek() && m_stream.SeekI(m_ofsOrig) == wxInvalidOffset )
720
            return R(0);
721
722
        return retval;
723
    }
724
725
    wxInputStream& m_stream;
726
    const wxFileOffset m_ofsOrig;
727
728
    wxDECLARE_NO_COPY_CLASS(wxInputStreamPeeker);
729
};
730
731
#endif // wxUSE_STREAMS
732
733
#endif // _WX_WXSTREAM_H__