139 lines
5.0 KiB
C#
139 lines
5.0 KiB
C#
|
using System;
|
|||
|
using System.Buffers.Binary;
|
|||
|
using System.IO;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
|
|||
|
namespace Ryujinx.Common
|
|||
|
{
|
|||
|
public static class StreamExtensions
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Writes a <cref="ReadOnlySpan<int>" /> to this stream.
|
|||
|
///
|
|||
|
/// This default implementation converts each buffer value to a stack-allocated
|
|||
|
/// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="buffer">The buffer of values to be written</param>
|
|||
|
public static void Write(this Stream stream, ReadOnlySpan<int> buffer)
|
|||
|
{
|
|||
|
if (buffer.Length == 0)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (BitConverter.IsLittleEndian)
|
|||
|
{
|
|||
|
ReadOnlySpan<byte> byteBuffer = MemoryMarshal.Cast<int, byte>(buffer);
|
|||
|
stream.Write(byteBuffer);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Span<byte> byteBuffer = stackalloc byte[sizeof(int)];
|
|||
|
|
|||
|
foreach (int value in buffer)
|
|||
|
{
|
|||
|
BinaryPrimitives.WriteInt32LittleEndian(byteBuffer, value);
|
|||
|
stream.Write(byteBuffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes a four-byte signed integer to this stream. The current position
|
|||
|
/// of the stream is advanced by four.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="value">The value to be written</param>
|
|||
|
public static void Write(this Stream stream, int value)
|
|||
|
{
|
|||
|
Span<byte> buffer = stackalloc byte[sizeof(int)];
|
|||
|
BinaryPrimitives.WriteInt32LittleEndian(buffer, value);
|
|||
|
stream.Write(buffer);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes an eight-byte signed integer to this stream. The current position
|
|||
|
/// of the stream is advanced by eight.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="value">The value to be written</param>
|
|||
|
public static void Write(this Stream stream, long value)
|
|||
|
{
|
|||
|
Span<byte> buffer = stackalloc byte[sizeof(long)];
|
|||
|
BinaryPrimitives.WriteInt64LittleEndian(buffer, value);
|
|||
|
stream.Write(buffer);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
// Writes a four-byte unsigned integer to this stream. The current position
|
|||
|
// of the stream is advanced by four.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="value">The value to be written</param>
|
|||
|
public static void Write(this Stream stream, uint value)
|
|||
|
{
|
|||
|
Span<byte> buffer = stackalloc byte[sizeof(uint)];
|
|||
|
BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
|
|||
|
stream.Write(buffer);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes an eight-byte unsigned integer to this stream. The current
|
|||
|
/// position of the stream is advanced by eight.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="value">The value to be written</param>
|
|||
|
public static void Write(this Stream stream, ulong value)
|
|||
|
{
|
|||
|
Span<byte> buffer = stackalloc byte[sizeof(ulong)];
|
|||
|
BinaryPrimitives.WriteUInt64LittleEndian(buffer, value);
|
|||
|
stream.Write(buffer);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes the contents of source to stream by calling source.CopyTo(stream).
|
|||
|
/// Provides consistency with other Stream.Write methods.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to</param>
|
|||
|
/// <param name="source">The stream to be read from</param>
|
|||
|
public static void Write(this Stream stream, Stream source)
|
|||
|
{
|
|||
|
source.CopyTo(stream);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes a sequence of bytes to the Stream.
|
|||
|
/// </summary>
|
|||
|
/// <param name="stream">The stream to be written to.</param>
|
|||
|
/// <param name="value">The byte to be written</param>
|
|||
|
/// <param name="count">The number of times the value should be written</param>
|
|||
|
public static void WriteByte(this Stream stream, byte value, int count)
|
|||
|
{
|
|||
|
if (count <= 0)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
const int BlockSize = 16;
|
|||
|
|
|||
|
int blockCount = count / BlockSize;
|
|||
|
if (blockCount > 0)
|
|||
|
{
|
|||
|
Span<byte> span = stackalloc byte[BlockSize];
|
|||
|
span.Fill(value);
|
|||
|
for (int x = 0; x < blockCount; x++)
|
|||
|
{
|
|||
|
stream.Write(span);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int nonBlockBytes = count % BlockSize;
|
|||
|
for (int x = 0; x < nonBlockBytes; x++)
|
|||
|
{
|
|||
|
stream.WriteByte(value);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|