BinaryReader.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. //
  2. // System.IO.BinaryReader
  3. //
  4. // Author:
  5. // Matt Kimball ([email protected])
  6. //
  7. using System;
  8. using System.Text;
  9. namespace System.IO {
  10. public class BinaryReader : IDisposable {
  11. Stream m_stream;
  12. Encoding m_encoding;
  13. int m_encoding_max_byte;
  14. byte[] m_buffer;
  15. int m_buffer_used;
  16. int m_buffer_pos;
  17. public BinaryReader(Stream input) : this(input, Encoding.UTF8) {
  18. }
  19. public BinaryReader(Stream input, Encoding encoding) {
  20. if (input == null || encoding == null)
  21. throw new ArgumentNullException();
  22. if (!input.CanRead)
  23. throw new ArgumentException();
  24. m_stream = input;
  25. m_encoding = encoding;
  26. m_encoding_max_byte = m_encoding.GetMaxByteCount(1);
  27. }
  28. public virtual Stream BaseStream {
  29. get {
  30. return m_stream;
  31. }
  32. }
  33. public virtual void Close() {
  34. Dispose();
  35. m_stream.Close();
  36. }
  37. public virtual void Dispose() {
  38. m_buffer = null;
  39. m_buffer_used = 0;
  40. }
  41. protected virtual void FillBuffer(int bytes) {
  42. if (!EnsureBuffered(m_buffer_used - m_buffer_pos + bytes)) {
  43. throw new EndOfStreamException();
  44. }
  45. }
  46. public virtual int PeekChar() {
  47. EnsureBuffered(m_encoding_max_byte);
  48. int i;
  49. for (i = 1; m_encoding.GetCharCount(m_buffer, m_buffer_pos, i) == 0; i++) {
  50. if (m_buffer_pos + i >= m_buffer_used) {
  51. return -1;
  52. }
  53. }
  54. char[] decode = m_encoding.GetChars(m_buffer, m_buffer_pos, i);
  55. return decode[0];
  56. }
  57. public virtual int Read() {
  58. char[] decode = new char[1];
  59. Read(decode, 0, 1);
  60. return decode[0];
  61. }
  62. public virtual int Read(byte[] buffer, int index, int count) {
  63. if (buffer == null) {
  64. throw new ArgumentNullException();
  65. }
  66. if (buffer.Length - index < count) {
  67. throw new ArgumentException();
  68. }
  69. if (index < 0 || count < 0) {
  70. throw new ArgumentOutOfRangeException();
  71. }
  72. EnsureBuffered(count);
  73. if (m_buffer_used - m_buffer_pos < count) {
  74. count = m_buffer_used - m_buffer_pos;
  75. }
  76. Array.Copy(m_buffer, m_buffer_pos, buffer, index, count);
  77. ConsumeBuffered(count);
  78. return count;
  79. }
  80. public virtual int Read(char[] buffer, int index, int count) {
  81. if (buffer == null) {
  82. throw new ArgumentNullException();
  83. }
  84. if (buffer.Length - index < count) {
  85. throw new ArgumentException();
  86. }
  87. if (index < 0 || count < 0) {
  88. throw new ArgumentOutOfRangeException();
  89. }
  90. EnsureBuffered(m_encoding_max_byte * count);
  91. int i;
  92. for (i = 1; m_encoding.GetCharCount(m_buffer, m_buffer_pos, i) < count; i++) {
  93. if (m_buffer_pos + i >= m_buffer_used) {
  94. break;
  95. }
  96. }
  97. count = m_encoding.GetCharCount(m_buffer, m_buffer_pos, i);
  98. char[] dec = m_encoding.GetChars(m_buffer, m_buffer_pos, i);
  99. Array.Copy(dec, 0, buffer, index, count);
  100. ConsumeBuffered(i);
  101. return count;
  102. }
  103. protected int Read7BitEncodedInt() {
  104. int ret = 0;
  105. int shift = 0;
  106. int count = 0;
  107. byte b;
  108. do {
  109. if (!EnsureBuffered(++count)) {
  110. throw new EndOfStreamException();
  111. }
  112. b = m_buffer[m_buffer_pos + count - 1];
  113. ret = ret | ((b & 0x7f) << shift);
  114. shift += 7;
  115. } while ((b & 0x80) == 0x80);
  116. ConsumeBuffered(count);
  117. return ret;
  118. }
  119. public virtual bool ReadBoolean() {
  120. if (!EnsureBuffered(1)) {
  121. throw new EndOfStreamException();
  122. }
  123. bool ret = BitConverter.ToBoolean(m_buffer, m_buffer_pos);
  124. ConsumeBuffered(1);
  125. return ret;
  126. }
  127. public virtual byte ReadByte() {
  128. if (!EnsureBuffered(1)) {
  129. throw new EndOfStreamException();
  130. }
  131. byte ret = m_buffer[m_buffer_pos];
  132. ConsumeBuffered(1);
  133. return ret;
  134. }
  135. public virtual byte[] ReadBytes(int count) {
  136. if (count < 0) {
  137. throw new ArgumentOutOfRangeException();
  138. }
  139. EnsureBuffered(count);
  140. if (count > m_buffer_used - m_buffer_pos) {
  141. count = m_buffer_used - m_buffer_pos;
  142. }
  143. if (count == 0) {
  144. throw new EndOfStreamException();
  145. }
  146. byte[] buf = new byte[count];
  147. Read(buf, 0, count);
  148. return buf;
  149. }
  150. public virtual char ReadChar() {
  151. char[] buf = ReadChars(1);
  152. return buf[0];
  153. }
  154. public virtual char[] ReadChars(int count) {
  155. if (count < 0) {
  156. throw new ArgumentOutOfRangeException();
  157. }
  158. char[] full = new char[count];
  159. count = Read(full, 0, count);
  160. if (count != full.Length) {
  161. char[] ret = new char[count];
  162. Array.Copy(full, 0, ret, 0, count);
  163. return ret;
  164. } else {
  165. return full;
  166. }
  167. }
  168. unsafe public virtual decimal ReadDecimal() {
  169. if (!EnsureBuffered(16)) {
  170. throw new EndOfStreamException();
  171. }
  172. decimal ret;
  173. byte* ret_ptr = (byte *)&ret;
  174. for (int i = 0; i < 16; i++) {
  175. ret_ptr[i] = m_buffer[m_buffer_pos + i];
  176. }
  177. ConsumeBuffered(16);
  178. return ret;
  179. }
  180. public virtual double ReadDouble() {
  181. if (!EnsureBuffered(8)) {
  182. throw new EndOfStreamException();
  183. }
  184. double ret = BitConverter.ToDouble(m_buffer, m_buffer_pos);
  185. ConsumeBuffered(8);
  186. return ret;
  187. }
  188. public virtual short ReadInt16() {
  189. if (!EnsureBuffered(2)) {
  190. throw new EndOfStreamException();
  191. }
  192. short ret = BitConverter.ToInt16(m_buffer, m_buffer_pos);
  193. ConsumeBuffered(2);
  194. return ret;
  195. }
  196. public virtual int ReadInt32() {
  197. if (!EnsureBuffered(1)) {
  198. throw new EndOfStreamException();
  199. }
  200. int ret = BitConverter.ToInt32(m_buffer, m_buffer_pos);
  201. ConsumeBuffered(1);
  202. return ret;
  203. }
  204. public virtual long ReadInt64() {
  205. if (!EnsureBuffered(8)) {
  206. throw new EndOfStreamException();
  207. }
  208. long ret = BitConverter.ToInt64(m_buffer, m_buffer_pos);
  209. ConsumeBuffered(8);
  210. return ret;
  211. }
  212. [CLSCompliant(false)]
  213. unsafe public virtual sbyte ReadSByte() {
  214. if (!EnsureBuffered(1)) {
  215. throw new EndOfStreamException();
  216. }
  217. sbyte ret;
  218. byte* ret_ptr = (byte *)&ret;
  219. ret_ptr[0] = m_buffer[m_buffer_pos];
  220. ConsumeBuffered(1);
  221. return ret;
  222. }
  223. public virtual string ReadString() {
  224. int len = Read7BitEncodedInt();
  225. char[] str = ReadChars(len);
  226. string ret = "";
  227. for (int i = 0; i < str.Length; i++) {
  228. ret = ret + str[i];
  229. }
  230. return ret;
  231. }
  232. public virtual float ReadSingle() {
  233. if (!EnsureBuffered(4)) {
  234. throw new EndOfStreamException();
  235. }
  236. float ret = BitConverter.ToSingle(m_buffer, m_buffer_pos);
  237. ConsumeBuffered(4);
  238. return ret;
  239. }
  240. [CLSCompliant(false)]
  241. public virtual ushort ReadUInt16() {
  242. if (!EnsureBuffered(2)) {
  243. throw new EndOfStreamException();
  244. }
  245. ushort ret = BitConverter.ToUInt16(m_buffer, m_buffer_pos);
  246. ConsumeBuffered(2);
  247. return ret;
  248. }
  249. [CLSCompliant(false)]
  250. public virtual uint ReadUInt32() {
  251. if (!EnsureBuffered(4)) {
  252. throw new EndOfStreamException();
  253. }
  254. uint ret = BitConverter.ToUInt32(m_buffer, m_buffer_pos);
  255. ConsumeBuffered(4);
  256. return ret;
  257. }
  258. [CLSCompliant(false)]
  259. public virtual ulong ReadUInt64() {
  260. if (!EnsureBuffered(8)) {
  261. throw new EndOfStreamException();
  262. }
  263. ulong ret = BitConverter.ToUInt64(m_buffer, m_buffer_pos);
  264. ConsumeBuffered(8);
  265. return ret;
  266. }
  267. bool EnsureBuffered(int bytes) {
  268. int needed = bytes - (m_buffer_used - m_buffer_pos);
  269. if (needed <= 0)
  270. return true;
  271. if (m_buffer_used + needed > m_buffer.Length) {
  272. byte[] old_buffer = m_buffer;
  273. m_buffer = new byte[m_buffer_used + needed];
  274. Array.Copy(old_buffer, 0, m_buffer, 0, m_buffer_used);
  275. }
  276. m_buffer_used += m_stream.Read(m_buffer, m_buffer_used, needed);
  277. return (m_buffer_used >= m_buffer_pos + bytes);
  278. }
  279. void ConsumeBuffered(int bytes) {
  280. m_buffer_pos += bytes;
  281. if (m_buffer_pos == m_buffer_used) {
  282. m_buffer_pos = 0;
  283. }
  284. }
  285. }
  286. }