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 }