public void WriteByte(long index, byte value)
{
try
{
// Find the block affected.
long blockOffset;
DataBlock block = GetDataBlock(index, out blockOffset);
// If the byte is already in a memory block, modify it.
MemoryDataBlock memoryBlock = block as MemoryDataBlock;
if (memoryBlock != null)
{
memoryBlock.Data[index - blockOffset] = value;
return;
}
FileDataBlock fileBlock = (FileDataBlock)block;
// If the byte changing is the first byte in the block and the previous block is a memory block, extend that.
if (blockOffset == index && block.PreviousBlock != null)
{
MemoryDataBlock previousMemoryBlock = block.PreviousBlock as MemoryDataBlock;
if (previousMemoryBlock != null)
{
previousMemoryBlock.AddByteToEnd(value);
fileBlock.RemoveBytesFromStart(1);
if (fileBlock.Length == 0)
{
_dataMap.Remove(fileBlock);
}
return;
}
}
// If the byte changing is the last byte in the block and the next block is a memory block, extend that.
if (blockOffset + fileBlock.Length - 1 == index && block.NextBlock != null)
{
MemoryDataBlock nextMemoryBlock = block.NextBlock as MemoryDataBlock;
if (nextMemoryBlock != null)
{
nextMemoryBlock.AddByteToStart(value);
fileBlock.RemoveBytesFromEnd(1);
if (fileBlock.Length == 0)
{
_dataMap.Remove(fileBlock);
}
return;
}
}
// Split the block into a prefix and a suffix and place a memory block in-between.
FileDataBlock prefixBlock = null;
if (index > blockOffset)
{
prefixBlock = new FileDataBlock(fileBlock.FileOffset, index - blockOffset);
}
FileDataBlock suffixBlock = null;
if (index < blockOffset + fileBlock.Length - 1)
{
suffixBlock = new FileDataBlock(
fileBlock.FileOffset + index - blockOffset + 1,
fileBlock.Length - (index - blockOffset + 1));
}
block = _dataMap.Replace(block, new MemoryDataBlock(value));
if (prefixBlock != null)
{
_dataMap.AddBefore(block, prefixBlock);
}
if (suffixBlock != null)
{
_dataMap.AddAfter(block, suffixBlock);
}
}
finally
{
OnChanged(EventArgs.Empty);
}
}