public byte ReadByte(long index, out bool isChanged) { long startIndex = 0; isChanged = false; BytePart bytePart = BytePartGetInfo(index, out startIndex); FileBytePart fileBytePart = bytePart as FileBytePart; MemoryBytePart memoryBytePart = bytePart as MemoryBytePart; if (fileBytePart != null) { if (_fileDataStream.Position != fileBytePart.FilePartIndex + index - startIndex) { _fileDataStream.Position = fileBytePart.FilePartIndex + index - startIndex; } return((byte)_fileDataStream.ReadByte()); } if (memoryBytePart != null) { isChanged = true; return(memoryBytePart.Bytes[index - startIndex]); } else { throw new ArgumentNullException("index", "FileByteData.ReadByte: The internal BytePartList is corrupt."); } }
public bool IsChanged() { if (ReadOnly) { return(false); } if (Length != _fileDataStream.Length) { return(true); } long index = 0; for (LinkedListNode <BytePart> bp = _bytePartList.First; bp != null; bp = bp.Next) { FileBytePart fileBytePart = bp.Value as FileBytePart; if (fileBytePart == null || fileBytePart.FilePartIndex != index) { return(true); } index += fileBytePart.Length; } return(index != _fileDataStream.Length); }
public void CommitChanges() { if (ReadOnly) { throw new OperationCanceledException("FileByteData.CommitChanges: The data cannot be saved when the file is in read only mode."); } if (Length > _fileDataStream.Length) { _fileDataStream.SetLength(Length); } long index = 0; // run through the whole bytePart list for (LinkedListNode <BytePart> bp = _bytePartList.First; bp != null; bp = bp.Next) { // try to convert it to a FileBytePart FileBytePart fileBytePart = bp.Value as FileBytePart; // if it's a FileBytePart and the orig file position is different, move the FileBytePart to the new (expected) position if (fileBytePart != null && fileBytePart.FilePartIndex != index) { RearrangeFileBytePart(fileBytePart, index); } // increment the index to the next expected BytePart position for file - and memory parts index += bp.Value.Length; } index = 0; // run through the whole bytePart list again, now look at the memory parts for (LinkedListNode <BytePart> bp = _bytePartList.First; bp != null; bp = bp.Next) { // try to convert it to a MemoryBytePart MemoryBytePart memoryBytePart = bp.Value as MemoryBytePart; // if it's a MemoryBytePart if (memoryBytePart != null) { _fileDataStream.Position = index; // write the MemoryBytePart into the stream for (int memoryIndex = 0; memoryIndex < memoryBytePart.Length; memoryIndex += BLOCK_SIZE) { _fileDataStream.Write(memoryBytePart.Bytes, memoryIndex, (int)Math.Min(BLOCK_SIZE, memoryBytePart.Length - memoryIndex)); } } // increment the index to the next expected BytePart position for file - and memory parts index += bp.Value.Length; } _fileDataStream.Flush(); InitFileByteData(); }
void RearrangeFileBytePart(FileBytePart bytePart, long index) { long nextIndex = 0; byte[] buffer = new byte[BLOCK_SIZE]; FileBytePart nextFileBlock = GetNextFileBytePart(bytePart, index, out nextIndex); if (nextFileBlock != null && index + bytePart.Length > nextFileBlock.FilePartIndex) { RearrangeFileBytePart(nextFileBlock, nextIndex); } if (bytePart.FilePartIndex > index) { Array.Clear(buffer, 0, buffer.Length); for (long relIndex = 0; relIndex < bytePart.Length; relIndex += buffer.Length) { int bytesToRead = (int)Math.Min(buffer.Length, bytePart.Length - relIndex); _fileDataStream.Position = bytePart.FilePartIndex + relIndex; _fileDataStream.Read(buffer, 0, bytesToRead); _fileDataStream.Position = index + relIndex; _fileDataStream.Write(buffer, 0, bytesToRead); } } else { Array.Clear(buffer, 0, buffer.Length); for (long relIndex = 0; relIndex < bytePart.Length; relIndex += buffer.Length) { int bytesToRead = (int)Math.Min(buffer.Length, bytePart.Length - relIndex); long readOffset = bytePart.FilePartIndex + bytePart.Length - relIndex - bytesToRead; _fileDataStream.Position = readOffset; _fileDataStream.Read(buffer, 0, bytesToRead); long writeOffset = index + bytePart.Length - relIndex - bytesToRead; _fileDataStream.Position = writeOffset; _fileDataStream.Write(buffer, 0, bytesToRead); } } bytePart.SetFilePartIndex(index); }
FileBytePart GetNextFileBytePart(BytePart bytePart, long index, out long nextIndex) { FileBytePart nextFileBytePart = null; nextIndex = index + bytePart.Length; LinkedListNode <BytePart> bp = _bytePartList.Find(bytePart); // run through the whole bytePart list from the current position + 1, to find the next FileBytePart for (LinkedListNode <BytePart> bp1 = bp.Next; bp1 != null; bp1 = bp1.Next) { FileBytePart fileBytePart = bp1.Value as FileBytePart; if (fileBytePart != null) { nextFileBytePart = fileBytePart; break; } nextIndex += bp1.Value.Length; } return(nextFileBytePart); }
public void InsertBytes(long index, byte[] value, bool track_Change = true) { if (track_Change) { _undoList.Add(new UndoAction(value, index, mod_type.mod_insert)); } BytePart bytePart = BytePartGetInfo(index, out long startIndex); FileBytePart fileBytePart = bytePart as FileBytePart; MemoryBytePart memoryBytePart = bytePart as MemoryBytePart; if (memoryBytePart != null) { memoryBytePart.InsertBytes(index - startIndex, value); Length += value.Length; OnDataLengthChanged(EventArgs.Empty); OnDataChanged(EventArgs.Empty); return; } LinkedListNode <BytePart> bp = _bytePartList.Find(bytePart); if (startIndex == index && bp.Previous != null) { MemoryBytePart prevMemoryBytePart = bp.Previous.Value as MemoryBytePart; if (prevMemoryBytePart != null) { prevMemoryBytePart.InsertBytes(prevMemoryBytePart.Length, value); Length += value.Length; OnDataLengthChanged(EventArgs.Empty); OnDataChanged(EventArgs.Empty); return; } } if (fileBytePart != null) { FileBytePart newPrevFileBytePart = null; FileBytePart newNextFileBytePart = null; if (index > startIndex) { newPrevFileBytePart = new FileBytePart(fileBytePart.FilePartIndex, index - startIndex); } if (index < startIndex + fileBytePart.Length) { newNextFileBytePart = new FileBytePart( fileBytePart.FilePartIndex + index - startIndex, fileBytePart.Length - (index - startIndex)); } BytePart newBP = new MemoryBytePart(value); _bytePartList.Find(bytePart).Value = newBP; bytePart = newBP; if (newPrevFileBytePart != null) { LinkedListNode <BytePart> bp1 = _bytePartList.Find(bytePart); _bytePartList.AddBefore(bp1, newPrevFileBytePart); } if (newNextFileBytePart != null) { LinkedListNode <BytePart> bp2 = _bytePartList.Find(bytePart); _bytePartList.AddAfter(bp2, newNextFileBytePart); } Length += value.Length; OnDataLengthChanged(EventArgs.Empty); OnDataChanged(EventArgs.Empty); } else { throw new ArgumentNullException("index", "FileByteData.InsertBytes: The internal BytePartList is corrupt."); } }
public void WriteByte(long index, byte value, bool track_Change = true) { long startIndex = 0; byte oldValue = ReadByte(index); if (track_Change) { _undoList.Add(new UndoAction(new byte[] { oldValue }, index, mod_type.mod_replace)); } BytePart bytePart = BytePartGetInfo(index, out startIndex); FileBytePart fileBytePart = bytePart as FileBytePart; MemoryBytePart memoryBytePart = bytePart as MemoryBytePart; if (memoryBytePart != null) { memoryBytePart.Bytes[index - startIndex] = value; OnDataChanged(EventArgs.Empty); return; } if (fileBytePart != null) { LinkedListNode <BytePart> bp = _bytePartList.Find(bytePart); if (index == startIndex && bp.Previous != null) { MemoryBytePart prevMemoryBytePart = bp.Previous.Value as MemoryBytePart; if (prevMemoryBytePart != null) { prevMemoryBytePart.AddByteToEnd(value); fileBytePart.RemoveBytesFromStart(1); if (fileBytePart.Length == 0) { _bytePartList.Remove(fileBytePart); } OnDataChanged(EventArgs.Empty); return; } } if (index == startIndex + fileBytePart.Length - 1 && bp.Next != null) { MemoryBytePart nextMemoryBytePart = bp.Next.Value as MemoryBytePart; if (nextMemoryBytePart != null) { nextMemoryBytePart.AddByteToStart(value); fileBytePart.RemoveBytesFromEnd(1); if (fileBytePart.Length == 0) { _bytePartList.Remove(fileBytePart); } OnDataChanged(EventArgs.Empty); return; } } FileBytePart newPrevFileBytePart = null; FileBytePart newNextFileBytePart = null; if (index > startIndex) { newPrevFileBytePart = new FileBytePart(fileBytePart.FilePartIndex, index - startIndex); } if (index < startIndex + fileBytePart.Length - 1) { newNextFileBytePart = new FileBytePart( fileBytePart.FilePartIndex + index - startIndex + 1, fileBytePart.Length - (index - startIndex + 1)); } BytePart newMemoryBP = new MemoryBytePart(value); _bytePartList.Find(bytePart).Value = newMemoryBP; bytePart = newMemoryBP; if (newPrevFileBytePart != null) { LinkedListNode <BytePart> bp1 = _bytePartList.Find(bytePart); _bytePartList.AddBefore(bp1, newPrevFileBytePart); } if (newNextFileBytePart != null) { LinkedListNode <BytePart> bp2 = _bytePartList.Find(bytePart); _bytePartList.AddAfter(bp2, newNextFileBytePart); } OnDataChanged(EventArgs.Empty); } else { throw new ArgumentNullException("index", "FileByteData.WriteByte: The internal BytePartList is corrupt."); } }