BufferedStream.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //
  2. // System.IO.BufferedStream
  3. //
  4. // Author:
  5. // Matt Kimball ([email protected])
  6. // Ville Palo <[email protected]>
  7. //
  8. namespace System.IO {
  9. public sealed class BufferedStream : Stream {
  10. Stream m_stream;
  11. byte[] m_buffer;
  12. int m_buffer_pos;
  13. int m_buffer_read_ahead;
  14. bool m_buffer_reading;
  15. private bool disposed = false;
  16. public BufferedStream(Stream stream) : this(stream, 4096) {
  17. }
  18. public BufferedStream(Stream stream, int buffer_size) {
  19. if (stream == null)
  20. throw new ArgumentNullException ("stream was null");
  21. if (buffer_size < 0)
  22. throw new ArgumentOutOfRangeException ();
  23. m_stream = stream;
  24. m_buffer = new byte[buffer_size];
  25. }
  26. public override bool CanRead {
  27. get {
  28. return m_stream.CanRead;
  29. }
  30. }
  31. public override bool CanWrite {
  32. get {
  33. return m_stream.CanWrite;
  34. }
  35. }
  36. public override bool CanSeek {
  37. get {
  38. return m_stream.CanSeek;
  39. }
  40. }
  41. public override long Length {
  42. get {
  43. Flush ();
  44. return m_stream.Length;
  45. }
  46. }
  47. public override long Position {
  48. get {
  49. CheckObjectDisposedException ();
  50. return m_stream.Position - m_buffer_read_ahead + m_buffer_pos;
  51. }
  52. set {
  53. Flush();
  54. m_stream.Position = value;
  55. }
  56. }
  57. public override void Close() {
  58. if (m_buffer != null)
  59. Flush();
  60. m_stream.Close();
  61. m_buffer = null;
  62. disposed = true;
  63. }
  64. public override void Flush() {
  65. CheckObjectDisposedException ();
  66. if (m_buffer_reading) {
  67. if (CanSeek)
  68. m_stream.Position = Position;
  69. } else if (m_buffer_pos > 0) {
  70. m_stream.Write(m_buffer, 0, m_buffer_pos);
  71. }
  72. m_buffer_read_ahead = 0;
  73. m_buffer_pos = 0;
  74. }
  75. public override long Seek(long offset, SeekOrigin origin) {
  76. Flush();
  77. return m_stream.Seek(offset, origin);
  78. }
  79. public override void SetLength(long value) {
  80. m_stream.SetLength(value);
  81. }
  82. public override int ReadByte() {
  83. CheckObjectDisposedException ();
  84. byte[] b = new byte[1];
  85. if (Read(b, 0, 1) == 1) {
  86. return b[0];
  87. } else {
  88. return -1;
  89. }
  90. }
  91. public override void WriteByte(byte value) {
  92. CheckObjectDisposedException ();
  93. byte[] b = new byte[1];
  94. b[0] = value;
  95. Write(b, 0, 1);
  96. }
  97. public override int Read(byte[] array, int offset, int count) {
  98. CheckObjectDisposedException ();
  99. if (array.Length < offset + count)
  100. throw new ArgumentException ();
  101. if (offset < 0)
  102. throw new ArgumentOutOfRangeException ("Offset was negative value.");
  103. if (!m_buffer_reading) {
  104. Flush();
  105. m_buffer_reading = true;
  106. }
  107. if (count <= m_buffer_read_ahead - m_buffer_pos) {
  108. Array.Copy(m_buffer, m_buffer_pos, array, offset, count);
  109. m_buffer_pos += count;
  110. if (m_buffer_pos == m_buffer_read_ahead) {
  111. m_buffer_pos = 0;
  112. m_buffer_read_ahead = 0;
  113. }
  114. return count;
  115. }
  116. int ret = m_buffer_read_ahead - m_buffer_pos;
  117. Array.Copy(m_buffer, m_buffer_pos, array, offset, ret);
  118. m_buffer_pos = 0;
  119. m_buffer_read_ahead = 0;
  120. offset += ret;
  121. count -= ret;
  122. if (count >= m_buffer.Length) {
  123. ret += m_stream.Read(array, offset, count);
  124. } else {
  125. m_buffer_read_ahead = m_stream.Read(m_buffer, 0, m_buffer.Length);
  126. if (count < m_buffer_read_ahead) {
  127. Array.Copy(m_buffer, 0, array, offset, count);
  128. m_buffer_pos = count;
  129. ret += count;
  130. } else {
  131. Array.Copy(m_buffer, 0, array, offset, m_buffer_read_ahead);
  132. ret += m_buffer_read_ahead;
  133. m_buffer_read_ahead = 0;
  134. }
  135. }
  136. return ret;
  137. }
  138. public override void Write(byte[] array, int offset, int count) {
  139. CheckObjectDisposedException ();
  140. if (!m_stream.CanRead)
  141. throw new NotSupportedException ();
  142. if (offset < 0)
  143. throw new ArgumentOutOfRangeException ();
  144. if (m_buffer_reading) {
  145. Flush();
  146. m_buffer_reading = false;
  147. }
  148. if (m_buffer_pos + count >= m_buffer.Length) {
  149. Flush();
  150. m_stream.Write(array, offset, count);
  151. } else {
  152. Array.Copy(array, offset, m_buffer, m_buffer_pos, count);
  153. m_buffer_pos += count;
  154. }
  155. }
  156. private void CheckObjectDisposedException ()
  157. {
  158. if (disposed)
  159. throw new ObjectDisposedException ("BufferedStream", "Stream is closed");
  160. }
  161. }
  162. }