public override void Write(byte[] data) { ThrowIfEnded(); if (!IsSet) { throw new InvalidOperationException("Not set"); } // pass data through ContentTransform ContentTransform.Write(data); if (ContentTransform.Buffered == 0) { return; // no data available } data = ContentTransform.Read(); WriteTransformed(data); }
private int ProcessData(byte[] data, bool writeExcess) { ThrowIfEnded(); if (!IsSet) { throw new InvalidOperationException("Not set"); } int i = 0, len; char c; byte[] sliced; for (; i < data.Length;) { switch (State) { case BodyParserState.RawRead: len = ContentLength == -1 ? data.Length - i : Math.Min(data.Length - i, ContentLength - CurrentReadBytes); sliced = new byte[len]; Buffer.BlockCopy(data, i, sliced, 0, len); i += len; CurrentReadBytes += len; ContentTransform.Write(data); if (ContentTransform.Buffered > 0) { Readable.Write(ContentTransform.Read()); } if (CurrentReadBytes == ContentLength) { State = BodyParserState.Dormant; OnEnd?.Invoke(); break; } break; case BodyParserState.Chunked_Length: c = (char)data[i++]; if (c != CR) { StringQueue.Append(c); } else { if (!int.TryParse(StringQueue.Next(), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out int result)) { End(); return(-1); } chunkLen = result; State = BodyParserState.Chunked_LenLf; } break; case BodyParserState.Chunked_LenLf: c = (char)data[i++]; if (c != LF) { End(); return(-1); } if (chunkLen == 0) { State = BodyParserState.Chunked_Trailer; } else { State = BodyParserState.Chunked_ChunkData; } break; case BodyParserState.Chunked_ChunkData: len = Math.Min(data.Length - i, chunkLen - chunkIndex); sliced = new byte[len]; Buffer.BlockCopy(data, i, sliced, 0, len); i += len; CurrentReadBytes += len; chunkIndex += len; ContentTransform.Write(sliced); Readable.Write(ContentTransform.Read()); if (chunkLen == chunkIndex) { State = BodyParserState.Chunked_ChunkCr; } break; case BodyParserState.Chunked_ChunkCr: c = (char)data[i++]; if (c != CR) { End(); return(-1); } State = BodyParserState.Chunked_ChunkLf; break; case BodyParserState.Chunked_ChunkLf: c = (char)data[i++]; if (c != LF) { End(); return(-1); } State = BodyParserState.Chunked_Length; chunkLen = chunkIndex = 0; StringQueue.New(); break; case BodyParserState.Chunked_Trailer: c = (char)data[i++]; if (c != CR) { chunkIndex++; } else { if (chunkIndex == 0) { State = BodyParserState.Chunked_Lf; } else { chunkIndex = -1; // LF will be added } } break; case BodyParserState.Chunked_Lf: c = (char)data[i++]; if (c != LF) { End(); return(-1); } State = BodyParserState.Dormant; OnEnd?.Invoke(); ContentLength = CurrentReadBytes; break; default: throw new InvalidOperationException("ProcessData cannot execute on Dormant state"); } } if (writeExcess) { len = data.Length - i; sliced = new byte[len]; Buffer.BlockCopy(data, i, sliced, 0, len); Writable.Write(sliced); } return(i); }