-
Notifications
You must be signed in to change notification settings - Fork 3
/
SubStream.cs
executable file
·176 lines (154 loc) · 6.28 KB
/
SubStream.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace AOCapture
{
/**
* Takes a stream and only exposes a specified subsection of the stream.
*/
public class SubStream : Stream
{
private Stream stream;
private long startPosition;
private long endPosition;
/**
* Creates a stream that starts at the current position of the stream in the argument.
*/
public SubStream(Stream stream)
{
this.stream = stream;
this.startPosition = stream.Position;
}
/**
* Creates a stream that starts at the current position of the stream in the argument,
* and ends after length bytes.
*/
public SubStream(Stream stream, long length)
: this(stream)
{
this.endPosition = this.startPosition + length;
}
public override bool CanRead { get {return stream.CanRead;} }
public override bool CanSeek { get { return stream.CanSeek; } }
public override bool CanTimeout { get { return stream.CanTimeout; } }
public override bool CanWrite { get { return stream.CanWrite; } }
public override long Length { get { return this.endPosition - this.startPosition; } }
public override int ReadTimeout { get { return stream.ReadTimeout; } }
public override int WriteTimeout { get { return stream.WriteTimeout; } }
public override void Close() { stream.Close(); }
//HEY! Do I really want to dispose the underlying stream?
public new void Dispose() { stream.Dispose(); }
public override void Flush() { stream.Flush(); }
public override long Position {
set { this.Seek(value, SeekOrigin.Begin); }
get {
return this.stream.Position - this.startPosition;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if(this.stream.Position + count == this.endPosition + 1){
return 0;
}else if (this.stream.Position + count > this.endPosition) {
//HEY! Does my little equation still work if Position > endPosition? Just in case there's a bug
return this.stream.Read(buffer, offset, (int)(this.endPosition - this.stream.Position));
}else{
return this.stream.Read(buffer, offset, count);
}
}
public override int ReadByte()
{
if (this.stream.Position == this.endPosition) {
return -1;
} else {
return this.stream.ReadByte();
}
}
//Note: seeking beyond the length of the stream is *not* supported
public override long Seek(long offset, SeekOrigin origin)
{
//TODO: double-check the fenceposts
switch(origin){
case SeekOrigin.Begin:
if (this.startPosition + offset > this.endPosition || this.startPosition + offset < this.startPosition) {
throw new ArgumentException();
};
return this.stream.Seek(this.startPosition + offset, origin) - this.startPosition;
case SeekOrigin.Current:
if (this.stream.Position + offset > this.endPosition || this.stream.Position + offset < this.startPosition) {
throw new ArgumentException();
};
return this.stream.Seek(offset, origin) - this.startPosition;
case SeekOrigin.End:
if (this.endPosition + offset > this.endPosition || this.endPosition + offset < this.startPosition) {
throw new ArgumentException();
};
return this.stream.Seek(offset, origin) - this.startPosition;
default:
throw new ArgumentException();
}
}
public override void SetLength(long value)
{
//NOT IMPLEMENTED
}
public override void Write(byte[] buffer, int offset, int count)
{
//not implemented
}
static void Main(string[] args)
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("0123456789"));
SubStream ss1 = new SubStream(ms,5);
StreamReader sr1 = new StreamReader(ss1);
Console.Write("From 0 to 4: ");
while (sr1.Peek() >= 0) {
char[] c = new char[1];
sr1.Read(c,0,1);
Console.Write(c[0]+" ");
}
Console.WriteLine();
ss1.Position = 0;
ss1 = new SubStream(ms, 6);
sr1 = new StreamReader(ss1);
Console.Write("From 0 to 5: ");
while (sr1.Peek() >= 0) {
char[] c = new char[1];
sr1.Read(c, 0, 1);
Console.Write(c[0] + " ");
}
Console.WriteLine();
ms.Position = 3;
ss1 = new SubStream(ms, 3);
sr1 = new StreamReader(ss1);
Console.Write("From 3 to 5: ");
while (sr1.Peek() >= 0) {
char[] c = new char[1];
sr1.Read(c, 0, 1);
Console.Write(c[0] + " ");
}
Console.WriteLine();
Console.WriteLine();
ms.Position = 1;
ss1 = new SubStream(ms, 5);
ss1.Seek(2,SeekOrigin.Begin);
sr1 = new StreamReader(ss1);
Console.Write("From 3 to 5 (seek from 'Begin'): ");
while (sr1.Peek() >= 0) {
char[] c = new char[1];
sr1.Read(c, 0, 1);
Console.Write(c[0] + " ");
}
Console.WriteLine();
Console.WriteLine();
var binaryReader = new BinaryReader(ss1);
ss1.Position = 0;
int reddByte = binaryReader.ReadByte();
Console.Write("ReadByte: "+reddByte);
Console.WriteLine();
Console.WriteLine();
}
}
}