/// <summary> /// Reads <paramref name="count"/> bytes from the stream and appends them to the given <paramref name="buffer"/>. /// If <paramref name="count"/> is <c>Int32.MaxValue</c> the stream is read to the end. /// Unless <paramref name="preserveEndOfLines"/> is set the line endings in the appended data are normalized to "\n". /// </summary> public int AppendBytes(MutableString /*!*/ buffer, int count, bool preserveEndOfLines) { ContractUtils.RequiresNotNull(buffer, "buffer"); ContractUtils.Requires(count >= 0, "count"); if (count == 0) { return(0); } bool readAll = count == Int32.MaxValue; buffer.SwitchToBytes(); int initialBufferSize = buffer.GetByteCount(); if (preserveEndOfLines) { AppendRawBytes(buffer, count); } else { // allocate 3 more bytes at the end for a backstop and possible LF: byte[] bytes = Utils.EmptyBytes; int done = initialBufferSize; bool eof; do { AppendRawBytes(buffer, readAll ? 1024 : count); int end = buffer.GetByteCount(); int bytesRead = end - done; if (bytesRead == 0) { break; } eof = bytesRead < count; buffer.EnsureCapacity(end + 3); int byteCount; bytes = buffer.GetByteArray(out byteCount); if (bytes[end - 1] == CR && PeekByte(0) == LF) { ReadByte(); bytes[end++] = LF; } // insert backstop: bytes[end] = CR; bytes[end + 1] = LF; int last = IndexOfCrLf(bytes, done); count -= last - done; done = last; while (last < end) { int next = IndexOfCrLf(bytes, last + 2); int chunk = next - last - 1; Buffer.BlockCopy(bytes, last + 1, bytes, done, chunk); done += chunk; count -= chunk; last = next; } buffer.Remove(done); } while (readAll || count > 0 && !eof); } if (readAll) { buffer.TrimExcess(); } return(buffer.GetByteCount() - initialBufferSize); }
public int WriteBytes(MutableString /*!*/ buffer, int offset, int count, bool preserveEndOfLines) { // TODO: this is not safe, we are passing an internal pointer to the byte[] content of MutableString to the Stream: return(WriteBytes(buffer.SwitchToBytes().GetByteArrayChecked(offset, count), offset, count, preserveEndOfLines)); }