コード例 #1
0
        /// <summary>
        /// Function to open a chunk for reading.
        /// </summary>
        /// <param name="chunkId">The ID of the chunk to open.</param>
        /// <returns>A <see cref="GorgonBinaryReader" /> that will allow reading within the chunk.</returns>
        /// <remarks>
        /// <para>
        /// Use this to read data from a chunk within the file. If the <paramref name="chunkId"/> is not found, then this method will throw an exception. To mitigate this, check for the existence of a chunk in
        /// the <see cref="GorgonChunkFile{T}.Chunks"/> collection.
        /// </para>
        /// <para>
        /// This method will provide minimal validation for the chunk in that it will only check the <paramref name="chunkId"/> to see if it matches what's in the file, beyond that, the user is responsible for
        /// validating the data that lives within the chunk.
        /// </para>
        /// </remarks>
        /// <exception cref="IOException">Thrown if the chunk was opened without calling <see cref="GorgonChunkFile{T}.Open"/> first.</exception>
        /// <exception cref="GorgonException">Thrown when the <paramref name="chunkId" /> does not match the chunk in the file.</exception>
        /// <exception cref="KeyNotFoundException">Thrown when the <paramref name="chunkId" /> was not found in the chunk table.</exception>
        public override GorgonBinaryReader OpenChunk(ulong chunkId)
        {
            if (!IsOpen)
            {
                throw new IOException(Resources.GOR_ERR_CHUNK_FILE_NOT_OPEN);
            }

            ValidateChunkID(chunkId);

            GorgonChunk chunk = Chunks[chunkId];

            if (chunk.Equals(GorgonChunk.EmptyChunk))
            {
                throw new KeyNotFoundException(string.Format(Resources.GOR_ERR_CHUNK_NOT_FOUND, chunkId.FormatHex()));
            }

            if (_activeChunk.ID != 0)
            {
                if (_activeChunk.ID == chunkId)
                {
                    return(_activeReader);
                }

                CloseChunk();
            }

            _activeChunk = chunk;
            GorgonBinaryReader reader = null;

            // Validate the chunk ID at the offset.
            try
            {
                reader          = new GorgonBinaryReader(Stream, true);
                Stream.Position = ((long)_activeChunk.FileOffset + _headerEnd) - sizeof(long);

                ulong fileChunkId = reader.ReadUInt64();

                if (fileChunkId != _activeChunk.ID)
                {
                    throw new GorgonException(GorgonResult.CannotRead,
                                              string.Format(Resources.GOR_ERR_CHUNK_FILE_CHUNK_MISMATCH,
                                                            _activeChunk.FileOffset.FormatHex(),
                                                            _activeChunk.ID.FormatHex()));
                }
            }
            finally
            {
                reader?.Dispose();
            }

            _activeReader = new GorgonBinaryReader(new GorgonStreamWrapper(Stream, 0, _activeChunk.Size), true);

            return(_activeReader);
        }