2 // System.Net.ChunkStream
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2003 Ximian, Inc (http://www.ximian.com)
10 using System.Globalization;
26 WebHeaderCollection headers;
36 public ChunkStream (byte [] buffer, int offset, int size, WebHeaderCollection headers)
38 this.headers = headers;
39 ms = new MemoryStream ();
40 saved = new StringBuilder ();
43 Write (buffer, offset, size);
46 public void ResetBuffer ()
54 public void WriteAndReadBack (byte [] buffer, int offset, int size, ref int read)
56 Write (buffer, offset, offset+read);
57 read = Read (buffer, offset, size);
60 public int Read (byte [] buffer, int offset, int size)
62 ms.Position = readPosition;
63 int r = ms.Read (buffer, offset, size);
65 ms.Position = ms.Length;
69 public void Write (byte [] buffer, int offset, int size)
71 InternalWrite (buffer, ref offset, size);
74 void InternalWrite (byte [] buffer, ref int offset, int size)
76 if (state == State.None) {
77 state = GetChunkSize (buffer, ref offset, size);
78 if (state == State.None)
86 if (state == State.Body && offset < size) {
87 state = ReadBody (buffer, ref offset, size);
88 if (state == State.Body)
92 if (state == State.BodyFinished && offset < size) {
93 state = ReadCRLF (buffer, ref offset, size);
94 if (state == State.BodyFinished)
100 if (state == State.Trailer && offset < size) {
101 state = ReadTrailer (buffer, ref offset, size);
102 if (state == State.Trailer)
111 InternalWrite (buffer, ref offset, size);
114 public bool WantMore {
115 get { return (chunkRead != chunkSize || chunkSize != 0); }
119 get { return (Available == 0); }
122 public int Available {
123 get { return (int) (ms.Length - readPosition); }
126 State ReadBody (byte [] buffer, ref int offset, int size)
129 return State.BodyFinished;
131 int diff = size - offset;
132 if (diff + chunkRead > chunkSize)
133 diff = chunkSize - chunkRead;
135 ms.Write (buffer, offset, diff);
138 return (chunkRead == chunkSize) ? State.BodyFinished : State.Body;
142 State GetChunkSize (byte [] buffer, ref int offset, int size)
145 while (offset < size) {
146 c = (char) buffer [offset++];
149 throw new ProtocolViolationException ("2 CR found");
155 if (sawCR && c == '\n')
165 if (!sawCR || c != '\n')
169 chunkSize = Int32.Parse (saved.ToString (), NumberStyles.HexNumber);
171 return State.Trailer;
176 State ReadCRLF (byte [] buffer, ref int offset, int size)
179 if ((char) buffer [offset++] != '\r')
180 throw new ProtocolViolationException ("Expecting \\r");
184 return State.BodyFinished;
187 if ((char) buffer [offset++] != '\n')
188 throw new ProtocolViolationException ("Expecting \\n");
193 State ReadTrailer (byte [] buffer, ref int offset, int size)
198 if ((char) buffer [offset] == '\r') {
200 if ((char) buffer [offset] == '\n') {
208 string stString = "\r\n\r";
209 while (offset < size && st < 4) {
210 c = (char) buffer [offset++];
211 if ((st == 0 || st == 2) && c == '\r') {
216 if ((st == 1 || st == 3) && c == '\n') {
222 saved.Append (stString.Substring (0, st));
228 return State.Trailer;
230 StringReader reader = new StringReader (saved.ToString ());
232 while ((line = reader.ReadLine ()) != null && line != "")