yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Theresa FoleyCleanups related to RIFF support (#7041)4c76b2759

master
10.4 KiB329 linesraw
1#ifndef SLANG_CORE_STREAM_H
2#define SLANG_CORE_STREAM_H
3
4#include "slang-basic.h"
5
6namespace Slang
7{
8
9enum class StdStreamType
10{
11    ErrorOut,
12    Out,
13    In,
14    CountOf,
15};
16
17enum class SeekOrigin
18{
19    Start,   ///< Seek from the start of the stream
20    End,     ///< Seek from the end of the stream
21    Current, ///< Seek from the current cursor position
22};
23
24class Stream : public RefObject
25{
26public:
27    virtual ~Stream() {}
28    /// Get the current 'cursor' position in the stream
29    virtual Int64 getPosition() = 0;
30    /// Seek the cursor to a position. How the seek is performed is dependent on the 'origin' and
31    /// the offset required. NOTE that *any* seek will reset the 'end of stream' status. See 'read'
32    /// for requirements for 'isEnd' to be reached.
33    virtual SlangResult seek(SeekOrigin origin, Int64 offset) = 0;
34    /// Read from the current position into buffer.
35    /// If there are less bytes available than requested only the amount available will be read.
36    /// outReadBytes holds the actual amount of bytes read. It is valid (and not an error) for read
37    /// to return 0 bytes read - even if the end of the stream.
38    ///
39    /// 'isEnd' only becomes true when a read is performed *past* the end of a stream.
40    /// If a non zero read is performed from the end then isEnd must be true.
41    ///
42    /// Will return an error if there is a reading failure.
43    virtual SlangResult read(void* buffer, size_t length, size_t& outReadBytes) = 0;
44    /// Write to the stream from current position
45    virtual SlangResult write(const void* buffer, size_t length) = 0;
46    /// True if the of the stream has been hit. The 'read' method has more discussion as to when
47    /// this can occur.
48    virtual bool isEnd() = 0;
49    /// Returns true if it's possible to read from the stream.
50    virtual bool canRead() = 0;
51    /// Returns true when it's possible to write to the stream.
52    virtual bool canWrite() = 0;
53    /// Close the stream. Once closed no more operations can be performed on the stream.
54    /// Implies any pending data is flushed.
55    virtual void close() = 0;
56
57    /// Only applicable for write streams, flushes any buffers to underlying representation (such as
58    /// pipe, or file)
59    virtual SlangResult flush() = 0;
60
61    /// Helper function that will also *fail* if the specified amount of bytes aren't read.
62    SlangResult readExactly(void* buffer, size_t length);
63};
64
65enum class FileMode
66{
67    Create,
68    Open,
69    CreateNew,
70    Append
71};
72
73enum class FileAccess
74{
75    None = 0,
76    Read = 1,
77    Write = 2,
78    ReadWrite = 3
79};
80
81enum class FileShare
82{
83    None,
84    ReadOnly,
85    WriteOnly,
86    ReadWrite
87};
88
89/// Base class for memory streams. Only supports reading and does NOT own contained data.
90class MemoryStreamBase : public Stream
91{
92public:
93    typedef Stream Super;
94
95    virtual Int64 getPosition() SLANG_OVERRIDE { return m_position; }
96    virtual SlangResult seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
97    virtual SlangResult read(void* buffer, size_t length, size_t& outReadByts) SLANG_OVERRIDE;
98    virtual SlangResult write(const void* buffer, size_t length) SLANG_OVERRIDE
99    {
100        SLANG_UNUSED(buffer);
101        SLANG_UNUSED(length);
102        return SLANG_E_NOT_IMPLEMENTED;
103    }
104    virtual bool isEnd() SLANG_OVERRIDE { return m_atEnd; }
105    virtual bool canRead() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Read)) != 0; }
106    virtual bool canWrite() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Write)) != 0; }
107    virtual void close() SLANG_OVERRIDE { m_access = FileAccess::None; }
108    virtual SlangResult flush() SLANG_OVERRIDE
109    {
110        return canWrite() ? SLANG_OK : SLANG_E_NOT_AVAILABLE;
111    }
112
113    /// Get the contents
114    ConstArrayView<uint8_t> getContents() const
115    {
116        return ConstArrayView<uint8_t>(m_contents, m_contentsSize);
117    }
118
119    MemoryStreamBase(
120        FileAccess access = FileAccess::Read,
121        const void* contents = nullptr,
122        size_t contentsSize = 0)
123        : m_access(access)
124    {
125        _setContents(contents, contentsSize);
126    }
127
128protected:
129    /// Set to replace wholly current content with specified content
130    void _setContents(const void* contents, size_t contentsSize)
131    {
132        m_contents = (const uint8_t*)contents;
133        m_contentsSize = ptrdiff_t(contentsSize);
134        m_position = 0;
135        m_atEnd = false;
136    }
137    /// Update means that the content has changed, but position should be maintained
138    void _updateContents(const void* contents, size_t contentsSize)
139    {
140        const ptrdiff_t newPosition =
141            (m_position > ptrdiff_t(contentsSize)) ? ptrdiff_t(contentsSize) : m_position;
142        _setContents(contents, contentsSize);
143        m_position = newPosition;
144    }
145
146    const uint8_t* m_contents; ///< The content held in the stream
147
148    // Using ptrdiff_t (as opposed to size_t) as makes maths simpler
149    ptrdiff_t m_contentsSize; ///< Total size of the content in bytes
150    ptrdiff_t m_position; ///< The current position within content (valid values can only be between
151                          ///< 0 and m_contentSize)
152
153    bool
154        m_atEnd; ///< Happens when a read is done and nothing can be returned because already at end
155
156    FileAccess m_access;
157};
158
159/// Memory stream that owns it's contents
160class OwnedMemoryStream : public MemoryStreamBase
161{
162public:
163    typedef MemoryStreamBase Super;
164
165    virtual SlangResult write(const void* buffer, size_t length) SLANG_OVERRIDE;
166
167    /// Set the contents
168    void setContent(const void* contents, size_t contentsSize)
169    {
170        m_ownedContents.setCount(contentsSize);
171        if (contents != nullptr)
172        {
173            ::memcpy(m_ownedContents.getBuffer(), contents, contentsSize);
174        }
175        _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
176    }
177
178    void swapContents(List<uint8_t>& rhs)
179    {
180        rhs.swapWith(m_ownedContents);
181        _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
182    }
183
184    OwnedMemoryStream(FileAccess access)
185        : Super(access)
186    {
187    }
188
189protected:
190    List<uint8_t> m_ownedContents;
191};
192
193class FileStream : public Stream
194{
195public:
196    typedef Stream Super;
197
198    // Stream interface
199    virtual Int64 getPosition() SLANG_OVERRIDE;
200    virtual SlangResult seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
201    virtual SlangResult read(void* buffer, size_t length, size_t& outReadBytes) SLANG_OVERRIDE;
202    virtual SlangResult write(const void* buffer, size_t length) SLANG_OVERRIDE;
203    virtual bool canRead() SLANG_OVERRIDE;
204    virtual bool canWrite() SLANG_OVERRIDE;
205    virtual void close() SLANG_OVERRIDE;
206    virtual bool isEnd() SLANG_OVERRIDE;
207    virtual SlangResult flush() SLANG_OVERRIDE;
208
209    FileStream();
210
211    SlangResult init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share);
212    SlangResult init(const String& fileName, FileMode fileMode = FileMode::Open);
213
214    ~FileStream();
215
216private:
217    SlangResult _init(
218        const String& fileName,
219        FileMode fileMode,
220        FileAccess access,
221        FileShare share);
222
223    FILE* m_handle;
224    FileAccess m_fileAccess;
225    bool m_endReached = false;
226};
227
228/* A simple BufferedReader. The valid data is between m_startIndex and getCount().
229Can be used as a buffer to build up a result from a stream in memory using 'update' to read to the
230appropriate buffer size.
231*/
232class BufferedReadStream : public Stream
233{
234public:
235    typedef Stream Super;
236
237    virtual Int64 getPosition() SLANG_OVERRIDE;
238    virtual SlangResult seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
239    virtual SlangResult read(void* buffer, size_t length, size_t& outReadBytes) SLANG_OVERRIDE;
240    virtual SlangResult write(const void* buffer, size_t length) SLANG_OVERRIDE;
241    virtual bool canRead() SLANG_OVERRIDE;
242    virtual bool canWrite() SLANG_OVERRIDE;
243    virtual void close() SLANG_OVERRIDE;
244    virtual bool isEnd() SLANG_OVERRIDE;
245    virtual SlangResult flush() SLANG_OVERRIDE;
246
247    /// Will read assuming backing stream is
248    SlangResult update();
249
250    /// Consume bytes in the buffer.
251    void consume(Index byteCount);
252
253    Byte* getBuffer() { return m_buffer.getBuffer() + m_startIndex; }
254    const Byte* getBuffer() const { return m_buffer.getBuffer() + m_startIndex; }
255
256    size_t getCount() const { return m_buffer.getCount() - m_startIndex; }
257
258    /// Read until the buffer contains the specified amount of bytes
259    SlangResult readUntilContains(size_t size);
260
261    ConstArrayView<Byte> getView() const
262    {
263        return ConstArrayView<Byte>(getBuffer(), Index(getCount()));
264    }
265    ArrayView<Byte> getView() { return ArrayView<Byte>(getBuffer(), Index(getCount())); }
266
267    BufferedReadStream(Stream* stream)
268        : m_stream(stream), m_startIndex(0)
269    {
270    }
271
272protected:
273    void _resetBuffer()
274    {
275        m_startIndex = 0;
276        m_buffer.setCount(0);
277    }
278
279    size_t m_defaultReadSize = 1024; ///< When initiating a read the default read size
280    List<Byte> m_buffer;             ///< Holds the characters
281    Index m_startIndex;              ///< The start index
282    RefPtr<Stream> m_stream;         ///< Stream that is being read from
283};
284
285enum class StreamBufferStyle
286{
287    None,
288    Line,
289    Full,
290};
291
292struct StreamUtil
293{
294    // Write inputs to writeStream while simultaneously read from readStream and errStream.
295    static SlangResult readAndWrite(
296        Stream* writeStream,
297        ArrayView<Byte> bytesToWrite,
298        Stream* readStream,
299        List<Byte>& outReadBytes,
300        Stream* errStream,
301        List<Byte>& outErrBytes);
302
303    /// Appends all bytes that can be read from stream into bytes
304    static SlangResult readAll(Stream* stream, size_t readSize, List<Byte>& ioBytes);
305
306    /// Appends all bytes that can be read from stream into bytes
307    static SlangResult readAll(Stream* stream, List<Byte>& ioBytes)
308    {
309        return readAll(stream, 0, ioBytes);
310    }
311
312    /// Read as much as can be read until a 0 sized read, or an error and append onto ioBytes
313    /// Read size controls the size of each buffer read. Passing 0, will use the default read size.
314    static SlangResult read(Stream* stream, size_t readSize, List<Byte>& ioBytes);
315
316    static SlangResult discard(Stream* stream);
317
318    static SlangResult discardAll(Stream* stream);
319
320    static SlangResult readOrDiscard(Stream* stream, size_t readSize, List<Byte>* ioBytes);
321    static SlangResult readOrDiscardAll(Stream* stream, size_t readSize, List<Byte>* ioBytes);
322
323    static SlangResult setStreamBufferStyle(StdStreamType stdStream, StreamBufferStyle style);
324};
325
326
327} // namespace Slang
328
329#endif