/// <summary> /// Uses BinarySearch to locate the index of the block that contains start /// </summary> /// <param name="cache"></param> /// <param name="start"></param> /// <param name="match">True if match found. If this is false, the index returned is where the item would appear if it existed.</param> /// <returns>Index</returns> private int FindIndexOfBlockAtOffset(SparseMemoryStream cache, long start, out bool match) { if (cache.MemoryBlockCollection.Count == 0) { match = false; return(0); } // use BinarySearch to locate blocks of interest quickly if (_comparisonBlock == null) { _comparisonBlock = new MemoryStreamBlock(null, start); } else { _comparisonBlock.Offset = start; } int index = cache.MemoryBlockCollection.BinarySearch(_comparisonBlock); if (index < 0) // no match { // ~index represents the place at which the block we asked for // would appear if it existed index = ~index; match = false; } else { match = true; } return(index); }
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); } }
/// <summary> /// Uses BinarySearch to locate the index of the block that contains start /// </summary> /// <param name="cache"></param> /// <param name="start"></param> /// <param name="match">True if match found. If this is false, the index returned is where the item would appear if it existed.</param> /// <returns>Index</returns> private int FindIndexOfBlockAtOffset(SparseMemoryStream cache, long start, out bool match) { if (cache.MemoryBlockCollection.Count == 0) { match = false; return 0; } // use BinarySearch to locate blocks of interest quickly if (_comparisonBlock == null) _comparisonBlock = new MemoryStreamBlock(null, start); else _comparisonBlock.Offset = start; int index = cache.MemoryBlockCollection.BinarySearch(_comparisonBlock); if (index < 0) // no match { // ~index represents the place at which the block we asked for // would appear if it existed index = ~index; match = false; } else { match = true; } return index; }