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;
                }
            }
Exemple #2
0
        /// <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)));
        }