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