/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__ |