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