2 // System.IO.BinaryReader
5 // Matt Kimball (matt@kimball.net)
10 using System.Globalization;
13 public class BinaryReader : IDisposable {
16 int m_encoding_max_byte;
23 public BinaryReader(Stream input) : this(input, Encoding.UTF8) {
26 public BinaryReader(Stream input, Encoding encoding) {
27 if (input == null || encoding == null)
28 throw new ArgumentNullException(Locale.GetText ("Input or Encoding is a null reference."));
30 throw new ArgumentException(Locale.GetText ("The stream doesn't support reading."));
33 m_encoding = encoding;
34 m_encoding_max_byte = m_encoding.GetMaxByteCount(1);
35 m_buffer = new byte [32];
38 public virtual Stream BaseStream {
44 public virtual void Close() {
49 protected virtual void Dispose (bool disposing)
58 void IDisposable.Dispose()
63 protected virtual void FillBuffer(int bytes) {
64 if (!EnsureBuffered(m_buffer_used - m_buffer_pos + bytes)) {
65 throw new EndOfStreamException();
69 public virtual int PeekChar() {
70 EnsureBuffered(m_encoding_max_byte);
73 for (i = 1; m_encoding.GetCharCount(m_buffer, m_buffer_pos, i) == 0; i++) {
74 if (m_buffer_pos + i >= m_buffer_used) {
79 char[] decode = m_encoding.GetChars(m_buffer, m_buffer_pos, i);
83 public virtual int Read() {
84 char[] decode = new char[1];
90 public virtual int Read(byte[] buffer, int index, int count) {
92 throw new ArgumentNullException();
94 if (buffer.Length - index < count) {
95 throw new ArgumentException();
97 if (index < 0 || count < 0) {
98 throw new ArgumentOutOfRangeException();
101 EnsureBuffered(count);
103 if (m_buffer_used - m_buffer_pos < count) {
104 count = m_buffer_used - m_buffer_pos;
107 Array.Copy(m_buffer, m_buffer_pos, buffer, index, count);
109 ConsumeBuffered(count);
113 public virtual int Read(char[] buffer, int index, int count) {
114 if (buffer == null) {
115 throw new ArgumentNullException();
117 if (buffer.Length - index < count) {
118 throw new ArgumentException();
120 if (index < 0 || count < 0) {
121 throw new ArgumentOutOfRangeException();
124 EnsureBuffered(m_encoding_max_byte * count);
127 for (i = 1; m_encoding.GetCharCount(m_buffer, m_buffer_pos, i) < count; i++) {
128 if (m_buffer_pos + i >= m_buffer_used) {
133 count = m_encoding.GetCharCount(m_buffer, m_buffer_pos, i);
135 char[] dec = m_encoding.GetChars(m_buffer, m_buffer_pos, i);
136 Array.Copy(dec, 0, buffer, index, count);
142 protected int Read7BitEncodedInt() {
149 if (!EnsureBuffered(++count)) {
150 throw new EndOfStreamException();
152 b = m_buffer[m_buffer_pos + count - 1];
154 ret = ret | ((b & 0x7f) << shift);
156 } while ((b & 0x80) == 0x80);
158 ConsumeBuffered(count);
162 public virtual bool ReadBoolean() {
163 if (!EnsureBuffered(1)) {
164 throw new EndOfStreamException();
168 // true if the byte is non-zero; otherwise false.
169 bool ret = (m_buffer[m_buffer_pos] != 0);
174 public virtual byte ReadByte() {
175 if (!EnsureBuffered(1)) {
176 throw new EndOfStreamException();
179 byte ret = m_buffer[m_buffer_pos];
184 public virtual byte[] ReadBytes(int count) {
186 throw new ArgumentOutOfRangeException();
189 EnsureBuffered(count);
191 if (count > m_buffer_used - m_buffer_pos) {
192 count = m_buffer_used - m_buffer_pos;
196 throw new EndOfStreamException();
199 byte[] buf = new byte[count];
204 public virtual char ReadChar() {
205 char[] buf = ReadChars(1);
209 public virtual char[] ReadChars(int count) {
211 throw new ArgumentOutOfRangeException();
214 char[] full = new char[count];
215 count = Read(full, 0, count);
217 if (count != full.Length) {
218 char[] ret = new char[count];
219 Array.Copy(full, 0, ret, 0, count);
226 unsafe public virtual decimal ReadDecimal() {
227 if (!EnsureBuffered(16)) {
228 throw new EndOfStreamException();
232 byte* ret_ptr = (byte *)&ret;
233 for (int i = 0; i < 16; i++) {
234 ret_ptr[i] = m_buffer[m_buffer_pos + i];
241 public virtual double ReadDouble() {
242 if (!EnsureBuffered(8)) {
243 throw new EndOfStreamException();
246 double ret = BitConverter.ToDouble(m_buffer, m_buffer_pos);
251 public virtual short ReadInt16() {
252 if (!EnsureBuffered(2)) {
253 throw new EndOfStreamException();
256 short ret = (short) (m_buffer[m_buffer_pos] | (m_buffer[m_buffer_pos + 1] << 8));
261 public virtual int ReadInt32() {
262 if (!EnsureBuffered(4)) {
263 throw new EndOfStreamException();
266 int ret = (m_buffer[m_buffer_pos] |
267 (m_buffer[m_buffer_pos + 1] << 8) |
268 (m_buffer[m_buffer_pos + 2] << 16) |
269 (m_buffer[m_buffer_pos + 3] << 24)
275 public virtual long ReadInt64() {
276 if (!EnsureBuffered(8)) {
277 throw new EndOfStreamException();
280 uint ret_low = (uint) (m_buffer[m_buffer_pos] |
281 (m_buffer[m_buffer_pos + 1] << 8) |
282 (m_buffer[m_buffer_pos + 2] << 16) |
283 (m_buffer[m_buffer_pos + 3] << 24)
285 uint ret_high = (uint) (m_buffer[m_buffer_pos + 4] |
286 (m_buffer[m_buffer_pos + 5] << 8) |
287 (m_buffer[m_buffer_pos + 6] << 16) |
288 (m_buffer[m_buffer_pos + 7] << 24)
291 return (long) ((((ulong) ret_high) << 32) | ret_low);
294 [CLSCompliant(false)]
295 unsafe public virtual sbyte ReadSByte() {
296 if (!EnsureBuffered(1)) {
297 throw new EndOfStreamException();
301 byte* ret_ptr = (byte *)&ret;
302 ret_ptr[0] = m_buffer[m_buffer_pos];
308 public virtual string ReadString() {
309 int len = Read7BitEncodedInt();
311 char[] str = ReadChars(len);
313 for (int i = 0; i < str.Length; i++) {
320 public virtual float ReadSingle() {
321 if (!EnsureBuffered(4)) {
322 throw new EndOfStreamException();
325 float ret = BitConverter.ToSingle(m_buffer, m_buffer_pos);
330 [CLSCompliant(false)]
331 public virtual ushort ReadUInt16() {
332 if (!EnsureBuffered(2)) {
333 throw new EndOfStreamException();
336 ushort ret = (ushort) (m_buffer[m_buffer_pos] | (m_buffer[m_buffer_pos + 1] << 8));
341 [CLSCompliant(false)]
342 public virtual uint ReadUInt32() {
343 if (!EnsureBuffered(4)) {
344 throw new EndOfStreamException();
347 uint ret = (uint) (m_buffer[m_buffer_pos] |
348 (m_buffer[m_buffer_pos + 1] << 8) |
349 (m_buffer[m_buffer_pos + 2] << 16) |
350 (m_buffer[m_buffer_pos + 3] << 24)
356 [CLSCompliant(false)]
357 public virtual ulong ReadUInt64() {
358 if (!EnsureBuffered(8)) {
359 throw new EndOfStreamException();
362 uint ret_low = (uint) (m_buffer[m_buffer_pos] |
363 (m_buffer[m_buffer_pos + 1] << 8) |
364 (m_buffer[m_buffer_pos + 2] << 16) |
365 (m_buffer[m_buffer_pos + 3] << 24)
367 uint ret_high = (uint) (m_buffer[m_buffer_pos + 4] |
368 (m_buffer[m_buffer_pos + 5] << 8) |
369 (m_buffer[m_buffer_pos + 6] << 16) |
370 (m_buffer[m_buffer_pos + 7] << 24)
373 return (((ulong) ret_high) << 32) | ret_low;
377 bool EnsureBuffered(int bytes) {
378 int needed = bytes - (m_buffer_used - m_buffer_pos);
382 if (m_buffer_used + needed > m_buffer.Length) {
383 byte[] old_buffer = m_buffer;
384 m_buffer = new byte[m_buffer_used + needed];
385 Array.Copy(old_buffer, 0, m_buffer, 0, m_buffer_used);
386 m_buffer_pos = m_buffer_used;
389 int n = m_stream.Read(m_buffer, m_buffer_used, needed);
390 if (n == 0) return false;
394 return (m_buffer_used >= m_buffer_pos + bytes);
398 void ConsumeBuffered(int bytes) {
399 m_buffer_pos += bytes;