Fri Jun 14 16:21:54 CEST 2002 Paolo Molaro <lupus@ximian.com>
[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                         m_stream = null;
63                         m_buffer = null;
64                 }
65
66                 public override void Flush() {
67                         if (m_buffer_reading) {
68                                 m_stream.Position = Position;
69                         } else {
70                                 m_stream.Write(m_buffer, 0, m_buffer_pos);
71                         }
72
73                         m_buffer_read_ahead = 0;
74                         m_buffer_pos = 0;
75                 }
76
77                 public override long Seek(long offset, SeekOrigin origin) {
78                         Flush();
79                         return m_stream.Seek(offset, origin);
80                 }
81
82                 public override void SetLength(long value) {
83                         m_stream.SetLength(value);
84                 }
85
86                 public override int ReadByte() {
87                         byte[] b = new byte[1];
88
89                         if (Read(b, 0, 1) == 1) {
90                                 return b[0];
91                         } else {
92                                 return -1;
93                         }
94                 }
95
96                 public override void WriteByte(byte value) {
97                         byte[] b = new byte[1];
98
99                         b[0] = value;
100                         Write(b, 0, 1);
101                 }
102
103                 public override int Read(byte[] array, int offset, int count) {
104                         if (!m_buffer_reading) {
105                                 Flush();
106                                 m_buffer_reading = true;
107                         }
108
109                         if (count <= m_buffer_read_ahead - m_buffer_pos) {
110                                 Array.Copy(m_buffer, m_buffer_pos, array, offset, count);
111
112                                 m_buffer_pos += count;
113                                 if (m_buffer_pos == m_buffer_read_ahead) {
114                                         m_buffer_pos = 0;
115                                         m_buffer_read_ahead = 0;
116                                 }
117
118                                 return count;
119                         }
120
121                         int ret = m_buffer_read_ahead - m_buffer_pos;
122                         Array.Copy(m_buffer, m_buffer_pos, array, offset, ret);
123                         m_buffer_pos = 0;
124                         m_buffer_read_ahead = 0;
125                         offset += ret;
126                         count -= ret;
127
128                         if (count >= m_buffer.Length) {
129                                 ret += m_stream.Read(array, offset, count);
130                         } else {
131                                 m_buffer_read_ahead = m_stream.Read(m_buffer, 0, m_buffer.Length);
132                                 
133                                 if (count < m_buffer_read_ahead) {
134                                         Array.Copy(m_buffer, 0, array, offset, count);
135                                         m_buffer_pos = count;
136                                         ret += count;
137                                 } else {
138                                         Array.Copy(m_buffer, 0, array, offset, m_buffer_read_ahead);
139                                         ret += m_buffer_read_ahead;
140                                         m_buffer_read_ahead = 0;
141                                 }
142                         }
143
144                         return ret;
145                 }
146
147                 public override void Write(byte[] array, int offset, int count) {
148                         if (m_buffer_reading) {
149                                 Flush();
150                                 m_buffer_reading = false;
151                         }
152
153                         if (m_buffer_pos + count >= m_buffer.Length) {
154                                 Flush();
155                                 m_stream.Write(array, offset, count);
156                         } else {
157                                 Array.Copy(array, offset, m_buffer, m_buffer_pos, count);
158                                 m_buffer_pos += count;
159                         }
160                 }
161         }
162 }