public override void GetBlock(BlockArguments args) { int blockDataLength = m_blockDataLength; long pos = args.Position; if (IsDisposed || m_dataIoSession.IsDisposed) { throw new ObjectDisposedException(GetType().FullName); } if (pos < 0) { throw new ArgumentOutOfRangeException("position", "cannot be negative"); } if (pos >= (long)blockDataLength * (uint.MaxValue - 1)) { throw new ArgumentOutOfRangeException("position", "position reaches past the end of the file."); } uint physicalBlockIndex; uint indexPosition; if (pos <= uint.MaxValue) //64-bit divide is 2 times slower { indexPosition = ((uint)pos / (uint)blockDataLength); } else { indexPosition = (uint)((ulong)pos / (ulong)blockDataLength); //64-bit signed divide is twice as slow as 64-bit unsigned. } args.FirstPosition = (long)indexPosition * blockDataLength; args.Length = blockDataLength; if (args.IsWriting) { throw new Exception("File is read only"); } else { //Reading if (indexPosition >= m_stream.m_subFile.DataBlockCount) { throw new ArgumentOutOfRangeException("position", "position reaches past the end of the file."); } physicalBlockIndex = m_stream.m_subFile.DirectBlock + indexPosition; m_dataIoSession.Read(physicalBlockIndex, BlockType.DataBlock, indexPosition); args.FirstPointer = (IntPtr)m_dataIoSession.Pointer; args.SupportsWriting = false; } }
/// <summary> /// This uses the (blockIndex,offset) values to determine what the next block index is. /// This also has consistency checks to determine if the file is inconsistent (potentially corruption) /// </summary> /// <param name="blockIndex">the index of the block to read</param> /// <param name="offset">the offset inside the block to use to determine the next index block</param> /// <param name="blockType">the value 1-4 which tell what indirect block this is</param> /// <param name="blockBaseIndex">the lowest virtual address that can be referenced from this indirect block</param> /// <returns></returns> private uint GetBlockIndexValue(uint blockIndex, int offset, BlockType blockType, uint blockBaseIndex) { DiskIoSession buffer = m_ioSessions.SourceIndex; if (blockIndex == 0) { return(0); } //Skip the redundant read if this block is still cached. if (!buffer.IsValid || buffer.BlockIndex != blockIndex) { buffer.Read(blockIndex, blockType, blockBaseIndex); } return(*(uint *)(buffer.Pointer + (offset << 2))); }