/// <summary> /// Appends a block to the end of the underlying BlockArray. /// </summary> /// <param name="block">The block to append.</param> /// <remarks> /// <para> /// The underyling block array's SetExactSize() method will be /// called before appending the block. The stream position will /// be set to the end of the stream before the method returns. /// </para> /// <para> /// This method is a performance improvement over writing the /// a buffer to the stream via one of the write methods. /// </para> /// </remarks> public void Append(Block block) { blocks.SetExactSize(length); blocks.Append(block); length += block.Length; pos = length; }
/// <summary> /// Extracts a range of bytes from the array into newly /// created block array. /// </summary> /// <param name="index">Logical index of the first byte.</param> /// <param name="length">Number of bytes to extract.</param> /// <returns>A new block array referencing the bytes.</returns> /// <remarks> /// <note> /// Although this method does create a new BlockArray /// and Block objects, it does not copy the underlying buffers. /// Instead, it adjusts the new Block objects to reference the /// requested portions of the original underlying buffers. /// </note> /// </remarks> public BlockArray Extract(int index, int length) { BlockArray extracted = new BlockArray(); int cbRemain; int blockIndex; int pos; int cb; Block srcBlock; Block dstBlock; if (length <= 0) { return(extracted); } if (index + length > size) { throw new IndexOutOfRangeException(); } if (index == 0 && length == size) { // Return a clone of this instance. for (int i = 0; i < list.Count; i++) { srcBlock = list[i]; extracted.Append(new Block(srcBlock.Buffer, srcBlock.Offset, srcBlock.Length)); } return(extracted); } CalcPos(index); cbRemain = length; blockIndex = lastBlockIndex; srcBlock = list[blockIndex]; pos = lastBlockPos + srcBlock.Offset; while (true) { cb = srcBlock.Length + srcBlock.Offset - pos; if (cb > cbRemain) { cb = cbRemain; } dstBlock = new Block(srcBlock.Buffer, pos, cb); extracted.Append(dstBlock); cbRemain -= cb; if (cbRemain <= 0) { break; } srcBlock = list[++blockIndex]; pos = srcBlock.Offset; } return(extracted); }