private int ReadFromCache(SparseMemoryStream cache, long start, int count, byte[] buffer, int bufferOffset) { #if DEBUG // debug only check for valid parameters, as we generally expect callers to verify them PackagingUtilities.VerifyStreamReadArgs(this, buffer, bufferOffset, count); #endif Debug.Assert(cache != null); Debug.Assert(start >= 0); IList <MemoryStreamBlock> collection = cache.MemoryBlockCollection; checked { // use BinarySearch to locate blocks of interest quickly bool match; // exact match? int index = FindIndexOfBlockAtOffset(cache, start, out match); // if match was found, read from it int bytesRead = 0; if (match) { MemoryStreamBlock memStreamBlock = collection[index]; long overlapBlockOffset; long overlapBlockSize; // we have got an overlap which can be used to satisfy the read request, // at least partially PackagingUtilities.CalculateOverlap(memStreamBlock.Offset, memStreamBlock.Stream.Length, start, count, out overlapBlockOffset, out overlapBlockSize); if (overlapBlockSize > 0) { // overlap must be starting at the start as we know for sure that // memStreamBlock.Offset <= start Debug.Assert(overlapBlockOffset == start); memStreamBlock.Stream.Seek(overlapBlockOffset - memStreamBlock.Offset, SeekOrigin.Begin); // we know that memStream will return as much data as we requested // even if this logic changes we do not have to return everything // a partially complete read is acceptable here bytesRead = memStreamBlock.Stream.Read(buffer, bufferOffset, (int)overlapBlockSize); } } return(bytesRead); } }
public override int Read(byte[] buffer, int offset, int count) { int num3; this.CheckDisposed(); PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); if (count == 0) { return(0); } if (this._currentStreamLength <= this._currentStreamPosition) { return(0); } int num2 = (int)Math.Min((long)count, this._currentStreamLength - this._currentStreamPosition); if (this._isolatedStorageMode) { this._isolatedStorageStream.Seek(this._currentStreamPosition, SeekOrigin.Begin); num3 = this._isolatedStorageStream.Read(buffer, offset, num2); } else { Array.Clear(buffer, offset, num2); int num = this._memoryStreamList.BinarySearch(this.GetSearchBlockForOffset(this._currentStreamPosition)); if (num < 0) { num = ~num; } while (num < this._memoryStreamList.Count) { long num4; long num5; MemoryStreamBlock block = this._memoryStreamList[num]; PackagingUtilities.CalculateOverlap(block.Offset, (long)((int)block.Stream.Length), this._currentStreamPosition, (long)num2, out num5, out num4); if (num4 <= 0L) { break; } Array.Copy(block.Stream.GetBuffer(), (int)(num5 - block.Offset), buffer, (int)((offset + num5) - this._currentStreamPosition), (int)num4); num++; } num3 = num2; } this._currentStreamPosition += num3; return(num3); }
internal static PreSaveNotificationScanControlInstruction CommonPreSaveNotificationHandler(Stream stream, long offset, long size, long onDiskOffset, long onDiskSize, ref SparseMemoryStream cachePrefixStream) { if (size != 0L) { long num2; long num4; if (cachePrefixStream != null) { onDiskOffset += cachePrefixStream.Length; onDiskSize -= cachePrefixStream.Length; } if (onDiskSize == 0L) { return(PreSaveNotificationScanControlInstruction.Continue); } PackagingUtilities.CalculateOverlap(onDiskOffset, onDiskSize, offset, size, out num4, out num2); if (num2 <= 0L) { if (onDiskOffset <= offset) { return(PreSaveNotificationScanControlInstruction.Continue); } return(PreSaveNotificationScanControlInstruction.Stop); } long bytesToCopy = (num4 + num2) - onDiskOffset; if (cachePrefixStream == null) { cachePrefixStream = new SparseMemoryStream(0x19000L, 0xa00000L); } else { cachePrefixStream.Seek(0L, SeekOrigin.End); } stream.Seek(onDiskOffset, SeekOrigin.Begin); if (PackagingUtilities.CopyStream(stream, cachePrefixStream, bytesToCopy, 0x1000) != bytesToCopy) { throw new FileFormatException(SR.Get("CorruptedData")); } if ((onDiskOffset + onDiskSize) < (offset + size)) { return(PreSaveNotificationScanControlInstruction.Continue); } } return(PreSaveNotificationScanControlInstruction.Stop); }