/ src / Ryujinx.Common / Extensions / StreamExtensions.cs
StreamExtensions.cs
  1  using System;
  2  using System.Buffers.Binary;
  3  using System.IO;
  4  using System.Runtime.InteropServices;
  5  
  6  namespace Ryujinx.Common
  7  {
  8      public static class StreamExtensions
  9      {
 10          /// <summary>
 11          /// Writes a <cref="ReadOnlySpan<int>" /> to this stream.
 12          ///
 13          /// This default implementation converts each buffer value to a stack-allocated
 14          /// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
 15          /// </summary>
 16          /// <param name="stream">The stream to be written to</param>
 17          /// <param name="buffer">The buffer of values to be written</param>
 18          public static void Write(this Stream stream, ReadOnlySpan<int> buffer)
 19          {
 20              if (buffer.Length == 0)
 21              {
 22                  return;
 23              }
 24  
 25              if (BitConverter.IsLittleEndian)
 26              {
 27                  ReadOnlySpan<byte> byteBuffer = MemoryMarshal.Cast<int, byte>(buffer);
 28                  stream.Write(byteBuffer);
 29              }
 30              else
 31              {
 32                  Span<byte> byteBuffer = stackalloc byte[sizeof(int)];
 33  
 34                  foreach (int value in buffer)
 35                  {
 36                      BinaryPrimitives.WriteInt32LittleEndian(byteBuffer, value);
 37                      stream.Write(byteBuffer);
 38                  }
 39              }
 40          }
 41  
 42          /// <summary>
 43          /// Writes a four-byte signed integer to this stream. The current position
 44          /// of the stream is advanced by four.
 45          /// </summary>
 46          /// <param name="stream">The stream to be written to</param>
 47          /// <param name="value">The value to be written</param>
 48          public static void Write(this Stream stream, int value)
 49          {
 50              Span<byte> buffer = stackalloc byte[sizeof(int)];
 51              BinaryPrimitives.WriteInt32LittleEndian(buffer, value);
 52              stream.Write(buffer);
 53          }
 54  
 55          /// <summary>
 56          /// Writes an eight-byte signed integer to this stream. The current position
 57          /// of the stream is advanced by eight.
 58          /// </summary>
 59          /// <param name="stream">The stream to be written to</param>
 60          /// <param name="value">The value to be written</param>
 61          public static void Write(this Stream stream, long value)
 62          {
 63              Span<byte> buffer = stackalloc byte[sizeof(long)];
 64              BinaryPrimitives.WriteInt64LittleEndian(buffer, value);
 65              stream.Write(buffer);
 66          }
 67  
 68          /// <summary>
 69          // Writes a four-byte unsigned integer to this stream. The current position
 70          // of the stream is advanced by four.
 71          /// </summary>
 72          /// <param name="stream">The stream to be written to</param>
 73          /// <param name="value">The value to be written</param>
 74          public static void Write(this Stream stream, uint value)
 75          {
 76              Span<byte> buffer = stackalloc byte[sizeof(uint)];
 77              BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
 78              stream.Write(buffer);
 79          }
 80  
 81          /// <summary>
 82          /// Writes an eight-byte unsigned integer to this stream. The current
 83          /// position of the stream is advanced by eight.
 84          /// </summary>
 85          /// <param name="stream">The stream to be written to</param>
 86          /// <param name="value">The value to be written</param>
 87          public static void Write(this Stream stream, ulong value)
 88          {
 89              Span<byte> buffer = stackalloc byte[sizeof(ulong)];
 90              BinaryPrimitives.WriteUInt64LittleEndian(buffer, value);
 91              stream.Write(buffer);
 92          }
 93  
 94          /// <summary>
 95          /// Writes the contents of source to stream by calling source.CopyTo(stream).
 96          /// Provides consistency with other Stream.Write methods.
 97          /// </summary>
 98          /// <param name="stream">The stream to be written to</param>
 99          /// <param name="source">The stream to be read from</param>
100          public static void Write(this Stream stream, Stream source)
101          {
102              source.CopyTo(stream);
103          }
104  
105          /// <summary>
106          /// Writes a sequence of bytes to the Stream.
107          /// </summary>
108          /// <param name="stream">The stream to be written to.</param>
109          /// <param name="value">The byte to be written</param>
110          /// <param name="count">The number of times the value should be written</param>
111          public static void WriteByte(this Stream stream, byte value, int count)
112          {
113              if (count <= 0)
114              {
115                  return;
116              }
117  
118              const int BlockSize = 16;
119  
120              int blockCount = count / BlockSize;
121              if (blockCount > 0)
122              {
123                  Span<byte> span = stackalloc byte[BlockSize];
124                  span.Fill(value);
125                  for (int x = 0; x < blockCount; x++)
126                  {
127                      stream.Write(span);
128                  }
129              }
130  
131              int nonBlockBytes = count % BlockSize;
132              for (int x = 0; x < nonBlockBytes; x++)
133              {
134                  stream.WriteByte(value);
135              }
136          }
137      }
138  }