public AvifItemData ReadItemData(ItemLocationEntry entry) { if (entry is null) { ExceptionUtil.ThrowArgumentNullException(nameof(entry)); } AvifItemData data; if (entry.Extents.Count == 1) { long offset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, entry.Extents[0]); this.reader.Position = offset; ulong totalItemSize = entry.TotalItemSize; if (totalItemSize <= ManagedAvifItemDataMaxSize) { ManagedAvifItemData managedItemData = new ManagedAvifItemData((int)totalItemSize, this.arrayPool); this.reader.ProperRead(managedItemData.GetBuffer(), 0, (int)managedItemData.Length); data = managedItemData; } else { UnmanagedAvifItemData unmanagedItemData = new UnmanagedAvifItemData(totalItemSize); try { this.reader.ProperRead(unmanagedItemData.UnmanagedBuffer, 0, totalItemSize); data = unmanagedItemData; unmanagedItemData = null; } finally { unmanagedItemData?.Dispose(); } } } else { data = ReadDataFromMultipleExtents(entry); } return(data); }
private AvifItemData ReadDataFromMultipleExtents(ItemLocationEntry entry) { AvifItemData data; IReadOnlyList <ItemLocationExtent> extents = entry.Extents; ulong totalItemSize = entry.TotalItemSize; if (totalItemSize <= ManagedAvifItemDataMaxSize) { ManagedAvifItemData managedItemData = new ManagedAvifItemData((int)totalItemSize, this.arrayPool); int offset = 0; int remainingBytes = (int)managedItemData.Length; byte[] bytes = managedItemData.GetBuffer(); for (int i = 0; i < extents.Count; i++) { ItemLocationExtent extent = extents[i]; long itemOffset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, extent); int length = (int)extent.Length; if (length > remainingBytes) { throw new FormatException("The extent length is greater than the number of bytes remaining for the item."); } this.reader.Position = itemOffset; this.reader.ProperRead(bytes, offset, length); offset += length; remainingBytes -= length; } if (remainingBytes > 0) { // This should never happen, the total item size is the sum of all the extent sizes. throw new FormatException("The item has more data than was read from the extents."); } data = managedItemData; } else { UnmanagedAvifItemData unmanagedItemData = new UnmanagedAvifItemData(totalItemSize); try { ulong offset = 0; ulong remainingBytes = totalItemSize; for (int i = 0; i < extents.Count; i++) { ItemLocationExtent extent = extents[i]; long itemOffset = CalculateExtentOffset(entry.BaseOffset, entry.ConstructionMethod, extent); ulong length = extent.Length; if (length > remainingBytes) { throw new FormatException("The extent length is greater than the number of bytes remaining for the item."); } this.reader.Position = itemOffset; this.reader.ProperRead(unmanagedItemData.UnmanagedBuffer, offset, length); offset += length; remainingBytes -= length; } if (remainingBytes > 0) { // This should never happen, the total item size is the sum of all the extent sizes. throw new FormatException("The item has more data than was read from the extents."); } data = unmanagedItemData; unmanagedItemData = null; } finally { unmanagedItemData?.Dispose(); } } return(data); }