StreamExtensions.cs 5.0 KB

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