StreamExtensions.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Text;
  6. namespace MatrixIO.IO
  7. {
  8. public static class StreamExtensions
  9. {
  10. public static byte ReadOneByte(this Stream stream)
  11. {
  12. return ReadBytes(stream, 1)[0];
  13. }
  14. public static byte[] ReadBytes(this Stream stream, int count, bool partial = true)
  15. {
  16. byte[] buffer = new byte[count];
  17. int len = stream.Read(buffer, 0, count);
  18. if (len < count)
  19. {
  20. if (!partial || len == 0) throw new EndOfStreamException();
  21. Array.Resize(ref buffer, len);
  22. }
  23. return buffer;
  24. }
  25. public static void WriteOneByte(this Stream stream, byte b)
  26. {
  27. byte[] buffer = new byte[] { b };
  28. stream.Write(buffer, 0, 1);
  29. }
  30. public static void WriteBytes(this Stream stream, byte[] bytes)
  31. {
  32. stream.Write(bytes, 0, bytes.Length);
  33. }
  34. #region BigEndian Read
  35. public static short ReadBEInt16(this Stream stream)
  36. {
  37. return BitConverter.ToInt16(stream.ReadBytes(2, false), 0).NetworkToHostOrder();
  38. }
  39. public static ushort ReadBEUInt16(this Stream stream)
  40. {
  41. return (ushort)ReadBEInt16(stream);
  42. }
  43. public static int ReadBEInt24(this Stream stream)
  44. {
  45. byte[] buffer = new byte[4];
  46. int len = stream.Read(buffer, 0, 3);
  47. if (len < 3) throw new EndOfStreamException();
  48. return BitConverter.ToInt32(buffer, 0).NetworkToHostOrder();
  49. }
  50. public static uint ReadBEUInt24(this Stream stream)
  51. {
  52. byte[] buffer = new byte[4];
  53. stream.Read(buffer, 1, 3);
  54. return BitConverter.ToUInt32(buffer, 0).NetworkToHostOrder();
  55. }
  56. public static int ReadBEInt32(this Stream stream)
  57. {
  58. return BitConverter.ToInt32(stream.ReadBytes(4, false), 0).NetworkToHostOrder();
  59. }
  60. public static uint ReadBEUInt32(this Stream stream)
  61. {
  62. return (uint)ReadBEInt32(stream);
  63. }
  64. public static long ReadBEInt64(this Stream stream)
  65. {
  66. return BitConverter.ToInt64(stream.ReadBytes(8, false), 0).NetworkToHostOrder();
  67. }
  68. public static ulong ReadBEUInt64(this Stream stream)
  69. {
  70. return (ulong)ReadBEInt64(stream);
  71. }
  72. #endregion
  73. #region BigEndian Write
  74. public static void WriteBEInt16(this Stream stream, short value)
  75. {
  76. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  77. stream.Write(buffer, 0, buffer.Length);
  78. }
  79. public static void WriteBEUInt16(this Stream stream, ushort value)
  80. {
  81. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  82. stream.Write(buffer, 0, buffer.Length);
  83. }
  84. public static void WriteBEInt24(this Stream stream, int value)
  85. {
  86. WriteBEUInt24(stream, (uint)value);
  87. }
  88. public static void WriteBEUInt24(this Stream stream, uint value)
  89. {
  90. if (value > 16777215) throw new OverflowException();
  91. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  92. stream.Write(buffer, 1, buffer.Length - 1);
  93. }
  94. public static void WriteBEInt32(this Stream stream, int value)
  95. {
  96. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  97. stream.Write(buffer, 0, buffer.Length);
  98. }
  99. public static void WriteBEUInt32(this Stream stream, uint value)
  100. {
  101. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  102. stream.Write(buffer, 0, buffer.Length);
  103. }
  104. public static void WriteBEInt64(this Stream stream, long value)
  105. {
  106. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  107. stream.Write(buffer, 0, buffer.Length);
  108. }
  109. public static void WriteBEUInt64(this Stream stream, ulong value)
  110. {
  111. byte[] buffer = BitConverter.GetBytes(value.HostToNetworkOrder());
  112. stream.Write(buffer, 0, buffer.Length);
  113. }
  114. #endregion
  115. public static string ReadNullTerminatedUTF8String(this Stream stream)
  116. {
  117. List<byte> bytes = new List<byte>();
  118. byte b;
  119. try
  120. {
  121. while ((b = stream.ReadOneByte()) > 0)
  122. {
  123. bytes.Add(b);
  124. if ((b & 0x80) == 0x80) // 0x1xxxxxxx
  125. {
  126. int continuations = 0;
  127. if (((b >> 5) & 0x06) == 0x06) continuations = 1; // 0x110xxxxx
  128. else if (((b >> 4) & 0x0E) == 0x0E) continuations = 2; // 0x1110xxxx
  129. else if (((b >> 3) & 0x0E) == 0x0E) continuations = 3; // 0x11110xxx
  130. for (int i = 0; i < continuations; i++)
  131. {
  132. byte c = stream.ReadOneByte();
  133. if (((c >> 6) & 0x02) == 0x02) bytes.Add(c); // 0x10xxxxxx
  134. else throw new FormatException("Invalid UTF-8 while reading null-terminated UTF-8 string.");
  135. }
  136. }
  137. }
  138. }
  139. catch (EndOfStreamException)
  140. {
  141. Trace.WriteLine("Last warning was expected.", "INFO");
  142. }
  143. if (bytes.Count > 0) return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
  144. else return null;
  145. }
  146. public static int WriteNullTerminatedUTF8String(this Stream stream, string text)
  147. {
  148. if (String.IsNullOrEmpty(text))
  149. {
  150. stream.WriteOneByte(0);
  151. return 1;
  152. }
  153. byte[] bytes = Encoding.UTF8.GetBytes(text);
  154. stream.Write(bytes, 0, bytes.Length);
  155. stream.WriteOneByte(0);
  156. return bytes.Length + 1;
  157. }
  158. public static int WriteUTF8String(this Stream stream, string text)
  159. {
  160. if (String.IsNullOrEmpty(text)) return 0;
  161. byte[] bytes = Encoding.UTF8.GetBytes(text);
  162. stream.Write(bytes, 0, bytes.Length);
  163. return bytes.Length;
  164. }
  165. }
  166. }