Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
ToSeekableInputStream.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Streams_ToSeekableInputStream_h_
5#define _Stroika_Foundation_Streams_ToSeekableInputStream_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
11
12/**
13 * \file
14 *
15 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
16 */
17
18namespace Stroika::Foundation::Streams::ToSeekableInputStream {
19
20 using InputStream::Ptr;
21
22 /**
23 * Not all input streams are seekable, but throwing a little memory at it, its easy to assure they are all
24 * seekable.
25 *
26 * That's what this utility does: maps the given input stream into a functionally identical one, except possibly
27 * adding seekability.
28 *
29 * If the argument stream is already seekable, New () just returns its argument (so perhaps a misnomer but I thought better
30 * to follow factory pattern).
31 *
32 * \par Example Usage
33 * \code
34 * InputStream::Ptr<byte> in = ToSeekableInputStream::New<byte> (existingInputStream);
35 * \endcode
36 *
37 * A socket is the canonical stream you might want this for: there is nowhere to seek back TO, because
38 * the bytes are gone once read (IO::Network::SocketStream::IsSeekable () returns false; so does
39 * InputStreamFromStdIStream constructed eNotSeekable - over cin, say). Wrapping one lets code that
40 * must read the same input twice do so:
41 *
42 * \par Example Usage
43 * \code
44 * SocketStream::Ptr socketStream = SocketStream::New (connectionSocket);
45 * InputStream::Ptr<byte> in = ToSeekableInputStream::New<byte> (socketStream);
46 * DoFirstPass (in);
47 * in.Seek (0); // legal only because of the wrapper; socketStream itself cannot seek
48 * DoSecondPass (in); // sees the very same bytes again, served out of the cache
49 * \endcode
50 *
51 * That two-pass shape is why this exists: see Providers::LibXML2::Provider::SAXParse (), which needs
52 * it when asked to both validate against a schema and report parse events, because that reads twice.
53 *
54 * \note this helper does not require it be given the input stream at SeekOffset 0, but for pretty obvious reasons
55 * it cannot produce a stream that permits seeking backwards from where it starts. This is checked via assertions.
56 *
57 * \note this helper may be problematic with very large streams, as it caches the stream in memory as it reads, and would
58 * eventually run out.
59 *
60 * \note ELEMENT_TYPE is effectively limited to byte today: SeekRead () accumulates into the cache through
61 * a hardcoded 'byte' buffer, so instantiating this for any other element type will not compile.
62 */
63 template <typename ELEMENT_TYPE>
64 auto New (const Ptr<ELEMENT_TYPE>& in) -> Ptr<ELEMENT_TYPE>;
65
66}
67
68/*
69 ********************************************************************************
70 ***************************** Implementation Details ***************************
71 ********************************************************************************
72 */
73#include "ToSeekableInputStream.inl"
74
75#endif /*_Stroika_Foundation_Streams_ToSeekableInputStream_h_*/