BinaryReader.cs 9.1 KB

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