/// <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); }