private static long CalcSize(SparseStream content, ServerSparseExtentHeader header) { long numDataGrains = StreamExtent.BlockCount(content.Extents, header.GrainSize * Sizes.Sector); long grainTableSectors = Utilities.Ceil(header.NumGTEsPerGT * 4, Sizes.Sector); return((grainTableSectors + (numDataGrains * header.GrainSize)) * Sizes.Sector); }
public bool TryAllocate(long length, out long start) { if (length % Sizes.OneMiB != 0) { throw new ArgumentException("VHDX free space must be managed on 1MB boundaries", nameof(length)); } for (int i = 0; i < _freeExtents.Count; ++i) { StreamExtent extent = _freeExtents[i]; if (extent.Length == length) { _freeExtents.RemoveAt(i); start = extent.Start; return(true); } if (extent.Length > length) { _freeExtents[i] = new StreamExtent(extent.Start + length, extent.Length - length); start = extent.Start; return(true); } } start = 0; return(false); }
internal override List <BuilderExtent> FixExtents(out long totalLength) { List <BuilderExtent> extents = new List <BuilderExtent>(); ServerSparseExtentHeader header = DiskImageFile.CreateServerSparseExtentHeader(_content.Length); GlobalDirectoryExtent gdExtent = new GlobalDirectoryExtent(header); long grainTableStart = (header.GdOffset * Sizes.Sector) + gdExtent.Length; long grainTableCoverage = header.NumGTEsPerGT * header.GrainSize * Sizes.Sector; foreach (var grainTableRange in StreamExtent.Blocks(_content.Extents, grainTableCoverage)) { for (int i = 0; i < grainTableRange.Count; ++i) { long grainTable = grainTableRange.Offset + i; long dataStart = grainTable * grainTableCoverage; GrainTableExtent gtExtent = new GrainTableExtent(grainTableStart, new SubStream(_content, dataStart, Math.Min(grainTableCoverage, _content.Length - dataStart)), header); extents.Add(gtExtent); gdExtent.SetEntry((int)grainTable, (uint)(grainTableStart / Sizes.Sector)); grainTableStart += gtExtent.Length; } } extents.Insert(0, gdExtent); header.FreeSector = (uint)(grainTableStart / Sizes.Sector); byte[] buffer = header.GetBytes(); extents.Insert(0, new BuilderBufferExtent(0, buffer)); totalLength = grainTableStart; return(extents); }
public override IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { CheckDisposed(); return (StreamExtent.Intersect( StreamExtent.Union(GetExtentsRaw(start, count), _parentStream.GetExtentsInRange(start, count)), new StreamExtent(start, count))); }
public override IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { StreamExtent lastRun = null; foreach (CompressedBlock block in Blocks) { if ((block.FirstSector + block.SectorCount) * Sizes.Sector < start) { // Skip blocks before start of range continue; } if (block.FirstSector * Sizes.Sector > start + count) { // Skip blocks after end of range continue; } foreach (CompressedRun run in block.Runs) { if (run.SectorCount > 0 && run.Type != RunType.Zeros) { long thisRunStart = (block.FirstSector + run.SectorStart) * Sizes.Sector; long thisRunEnd = thisRunStart + run.SectorCount * Sizes.Sector; thisRunStart = Math.Max(thisRunStart, start); thisRunEnd = Math.Min(thisRunEnd, start + count); long thisRunLength = thisRunEnd - thisRunStart; if (thisRunLength > 0) { if (lastRun != null && lastRun.Start + lastRun.Length == thisRunStart) { lastRun = new StreamExtent(lastRun.Start, lastRun.Length + thisRunLength); } else { if (lastRun != null) { yield return(lastRun); } lastRun = new StreamExtent(thisRunStart, thisRunLength); } } } } } if (lastRun != null) { yield return(lastRun); } }
private static long SectorsPresent(SparseStream content, long grainSize) { long total = 0; foreach (Range <long, long> grainRange in StreamExtent.Blocks(content.Extents, grainSize * Sizes.Sector)) { total += grainRange.Count * grainSize; } return(total); }
public void TestIntersect1() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(4, 8) }; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2)); }
public void TestUnion4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4), new StreamExtent(4, 4) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0, 8) }; Compare(r, StreamExtent.Union(s1)); }
protected override List <BuilderExtent> FixExtents(out long totalLength) { const int FooterSize = 512; const int DynHeaderSize = 1024; List <BuilderExtent> extents = new List <BuilderExtent>(); _footer.DataOffset = FooterSize; DynamicHeader dynHeader = new DynamicHeader(-1, FooterSize + DynHeaderSize, _blockSize, _footer.CurrentSize); BlockAllocationTableExtent batExtent = new BlockAllocationTableExtent(FooterSize + DynHeaderSize, dynHeader.MaxTableEntries); long streamPos = batExtent.Start + batExtent.Length; foreach (Range <long, long> blockRange in StreamExtent.Blocks(_content.Extents, _blockSize)) { for (int i = 0; i < blockRange.Count; ++i) { long block = blockRange.Offset + i; long blockStart = block * _blockSize; DataBlockExtent dataExtent = new DataBlockExtent(streamPos, new SubStream(_content, blockStart, Math.Min(_blockSize, _content.Length - blockStart))); extents.Add(dataExtent); batExtent.SetEntry((int)block, (uint)(streamPos / Sizes.Sector)); streamPos += dataExtent.Length; } } _footer.UpdateChecksum(); dynHeader.UpdateChecksum(); byte[] footerBuffer = new byte[FooterSize]; _footer.ToBytes(footerBuffer, 0); byte[] dynHeaderBuffer = new byte[DynHeaderSize]; dynHeader.ToBytes(dynHeaderBuffer, 0); // Add footer (to end) extents.Add(new BuilderBufferExtent(streamPos, footerBuffer)); totalLength = streamPos + FooterSize; extents.Insert(0, batExtent); extents.Insert(0, new BuilderBufferExtent(FooterSize, dynHeaderBuffer)); extents.Insert(0, new BuilderBufferExtent(0, footerBuffer)); return(extents); }
public void TestUnion3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(2, 8) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0, 10) }; Compare(r, StreamExtent.Union(s1, s2)); }
public void TestIntersect5() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 10) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 5) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3, 5) }; Compare(r, StreamExtent.Intersect(s1, s2)); }
internal override void PrepareForRead() { byte[] bitmap = new byte[Utilities.RoundUp(Utilities.Ceil(_content.Length, Sizes.Sector) / 8, Sizes.Sector)]; foreach (var range in StreamExtent.Blocks(_content.Extents, Sizes.Sector)) { for (int i = 0; i < range.Count; ++i) { byte mask = (byte)(1 << (7 - ((int)(range.Offset + i) % 8))); bitmap[(range.Offset + i) / 8] |= mask; } } _bitmapStream = new MemoryStream(bitmap, false); }
internal override void PrepareForRead() { long outputGrain = 0; _grainMapOffsets = new int[Length / (_grainSize * Sizes.Sector)]; _grainMapRanges = new Range <long, long> [_grainMapOffsets.Length]; foreach (Range <long, long> grainRange in StreamExtent.Blocks(_content.Extents, _grainSize * Sizes.Sector)) { for (int i = 0; i < grainRange.Count; ++i) { _grainMapOffsets[outputGrain] = i; _grainMapRanges[outputGrain] = grainRange; outputGrain++; } } }
public void TestIntersect4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 8) }; StreamExtent[] s3 = new StreamExtent[] { new StreamExtent(10, 10) }; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2, s3)); }
internal override void PrepareForRead() { _data = new byte[_gtesPerGt * 4]; long gtSpan = _gtesPerGt * _grainSize * Sizes.Sector; long sectorsAllocated = 0; foreach (var block in StreamExtent.Blocks(_content.Extents, _grainSize * Sizes.Sector)) { for (int i = 0; i < block.Count; ++i) { Utilities.WriteBytesLittleEndian((uint)(_dataStart + sectorsAllocated), _data, (int)((block.Offset + i) * 4)); sectorsAllocated += _grainSize; } } }
public void TestIntersect3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4), new StreamExtent(10, 10) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 8) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3, 1), new StreamExtent(10, 1) }; Compare(r, StreamExtent.Intersect(s1, s2)); }
/// <summary> /// Indicates if a stream contains a valid partition table. /// </summary> /// <param name="disk">The stream to inspect</param> /// <returns><c>true</c> if the partition table is valid, else <c>false</c>.</returns> public static bool IsValid(Stream disk) { if (disk.Length < Utilities.SectorSize) { return(false); } disk.Position = 0; byte[] bootSector = Utilities.ReadFully(disk, Utilities.SectorSize); // Check for the 'bootable sector' marker if (bootSector[510] != 0x55 || bootSector[511] != 0xAA) { return(false); } bool foundPartition = false; List <StreamExtent> knownPartitions = new List <StreamExtent>(); foreach (var record in ReadPrimaryRecords(bootSector)) { // If the partition extends beyond the end of the disk, this is probably an invalid partition table if (record.LBALength != 0xFFFFFFFF && (record.LBAStart + (long)record.LBALength) * Sizes.Sector > disk.Length) { return(false); } if (record.LBALength > 0) { foundPartition = true; } StreamExtent[] thisPartitionExtents = new StreamExtent[] { new StreamExtent(record.LBAStart, record.LBALength) }; // If the partition intersects another partition, this is probably an invalid partition table foreach (var overlap in StreamExtent.Intersect(knownPartitions, thisPartitionExtents)) { return(false); } knownPartitions = new List <StreamExtent>(StreamExtent.Union(knownPartitions, thisPartitionExtents)); } return(foundPartition); }
public override IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { CheckDisposed(); long maxCount = Math.Min(Length, start + count) - start; if (maxCount < 0) { return(new StreamExtent[0]); } IEnumerable <StreamExtent> parentExtents = _parentStream.GetExtentsInRange(start, maxCount); IEnumerable <StreamExtent> result = StreamExtent.Union(LayerExtents(start, maxCount), parentExtents); result = StreamExtent.Intersect(result, new[] { new StreamExtent(start, maxCount) }); return(result); }
public void ExtendTo(long fileSize, bool isFree) { if (fileSize % Sizes.OneMiB != 0) { throw new ArgumentException("VHDX space must be allocated on 1MB boundaries", "fileSize"); } if (fileSize < _fileSize) { throw new ArgumentOutOfRangeException("fileSize", "Attempt to extend file to smaller size", fileSize.ToString(CultureInfo.InvariantCulture)); } _fileSize = fileSize; if (isFree) { _freeExtents = new List <StreamExtent>(StreamExtent.Union(_freeExtents, new StreamExtent(_fileSize, fileSize - _fileSize))); } }
internal override void PrepareForRead() { byte[] grainTable = new byte[Utilities.RoundUp(_header.NumGTEsPerGT * 4, Sizes.Sector)]; long dataSector = (Start + grainTable.Length) / Sizes.Sector; _grainMapping = new List <long>(); _grainContiguousRangeMapping = new List <long>(); foreach (var grainRange in StreamExtent.Blocks(_content.Extents, _header.GrainSize * Sizes.Sector)) { for (int i = 0; i < grainRange.Count; ++i) { Utilities.WriteBytesLittleEndian((uint)dataSector, grainTable, (int)(4 * (grainRange.Offset + i))); dataSector += _header.GrainSize; _grainMapping.Add(grainRange.Offset + i); _grainContiguousRangeMapping.Add(grainRange.Count - i); } } _grainTableStream = new MemoryStream(grainTable, 0, grainTable.Length, false); }
private void StreamExtentSample() { // intro message Editor editor = GetEditor(); editor.WriteMessage("* StreamExtent *\n"); editor.WriteMessage("StreamExtent detects the extents of all the objects in the stream.\n"); editor.WriteMessage("Pick some objects in the current drawing and the extents will be highlighted.\n"); // pick multiple objects ObjectIdCollection ids = PickObjectSet(); if (ids.Count == 0) { editor.WriteMessage("No object is picked\n"); return; } Database db = GetDatabase(); StreamExtent stream = new StreamExtent(db); TransactionManager tm = db.TransactionManager; using (Transaction trans = tm.StartTransaction()) { stream.PushDisplayParameters(DictionaryDisplayConfiguration.GetStandardDisplayConfiguration(db), trans); foreach (ObjectId id in ids) { Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity; stream.Stream(ent); } stream.PopDisplayParameters(); trans.Commit(); } HighlightBoundBox3d(stream.Extents); }
public void TestBlocks() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(11, 4) }; List <Range <long, long> > ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.Equal(1, ranges.Count); Assert.Equal(0, ranges[0].Offset); Assert.Equal(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(9, 8) }; ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.Equal(1, ranges.Count); Assert.Equal(0, ranges[0].Offset); Assert.Equal(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.Equal(2, ranges.Count); Assert.Equal(0, ranges[0].Offset); Assert.Equal(3, ranges[0].Count); Assert.Equal(4, ranges[1].Offset); Assert.Equal(1, ranges[1].Count); }
public void TestBlockCount() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(11, 4) }; Assert.Equal(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(9, 8) }; Assert.Equal(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; Assert.Equal(4, StreamExtent.BlockCount(s, 10)); }
/// <summary> /// Creates a hex dump from a stream. /// </summary> /// <param name="stream">The stream to generate the hex dump from.</param> /// <param name="output">The destination for the hex dump.</param> public static void Generate(SparseStream stream, TextWriter output) { stream.Position = 0; byte[] buffer = new byte[1024 * 1024]; foreach (var block in StreamExtent.Blocks(stream.Extents, buffer.Length)) { long startPos = block.Offset * (long)buffer.Length; long endPos = Math.Min((block.Offset + block.Count) * (long)buffer.Length, stream.Length); stream.Position = startPos; while (stream.Position < endPos) { int numLoaded = 0; long readStart = stream.Position; while (numLoaded < buffer.Length) { int bytesRead = stream.Read(buffer, numLoaded, buffer.Length - numLoaded); if (bytesRead == 0) { break; } numLoaded += bytesRead; } for (int i = 0; i < numLoaded; i += 16) { bool foundVal = false; if (i > 0) { for (int j = 0; j < 16; j++) { if (buffer[i + j] != buffer[i + j - 16]) { foundVal = true; break; } } } else { foundVal = true; } if (foundVal) { output.Write("{0:x8}", i + readStart); for (int j = 0; j < 16; j++) { if (j % 8 == 0) { output.Write(" "); } output.Write(" {0:x2}", buffer[i + j]); } output.Write(" |"); for (int j = 0; j < 16; j++) { if (j % 8 == 0 && j != 0) { output.Write(" "); } output.Write("{0}", (buffer[i + j] >= 32 && buffer[i + j] < 127) ? (char)buffer[i + j] : '.'); } output.Write("|"); output.WriteLine(); } } } } }
public void TestIntersect1() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,4)}; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(4,8)}; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2)); }
public override IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { return(StreamExtent.Intersect( new[] { new StreamExtent(0, Capacity) }, new StreamExtent(start, count))); }
public void TestIntersect3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,4), new StreamExtent(10, 10)}; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3,8)}; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3,1), new StreamExtent(10,1)}; Compare(r, StreamExtent.Intersect(s1, s2)); }
public void TestUnion5() { StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Union()); }
/// <summary> /// Indicates if a stream contains a valid partition table. /// </summary> /// <param name="disk">The stream to inspect</param> /// <returns><c>true</c> if the partition table is valid, else <c>false</c>.</returns> public static bool IsValid(Stream disk) { if (disk.Length < Utilities.SectorSize) { return false; } disk.Position = 0; byte[] bootSector = Utilities.ReadFully(disk, Utilities.SectorSize); // Check for the 'bootable sector' marker if (bootSector[510] != 0x55 || bootSector[511] != 0xAA) { return false; } List<StreamExtent> knownPartitions = new List<StreamExtent>(); foreach (var record in ReadPrimaryRecords(bootSector)) { // If the partition extends beyond the end of the disk, this is probably an invalid partition table if (record.LBALength != 0xFFFFFFFF && (record.LBAStart + (long)record.LBALength) * Sizes.Sector > disk.Length) { return false; } if (record.LBALength > 0) { StreamExtent[] thisPartitionExtents = new StreamExtent[] { new StreamExtent(record.LBAStart, record.LBALength) }; // If the partition intersects another partition, this is probably an invalid partition table foreach (var overlap in StreamExtent.Intersect(knownPartitions, thisPartitionExtents)) { return false; } knownPartitions = new List<StreamExtent>(StreamExtent.Union(knownPartitions, thisPartitionExtents)); } } return true; }
public void Reserve(IEnumerable <StreamExtent> extents) { _freeExtents = new List <StreamExtent>(StreamExtent.Subtract(_freeExtents, extents)); }
public void Reserve(long start, long length) { ValidateRange(start, length, "reserve"); _freeExtents = new List <StreamExtent>(StreamExtent.Subtract(_freeExtents, new StreamExtent(start, length))); }
public void Release(long start, long length) { ValidateRange(start, length, "release"); _freeExtents = new List <StreamExtent>(StreamExtent.Union(_freeExtents, new StreamExtent(start, length))); }
public IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { return(StreamExtent.Intersect(Extents, new StreamExtent(start, count))); }
public void TestIntersect5() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,10)}; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3,5)}; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3,5)}; Compare(r, StreamExtent.Intersect(s1, s2)); }
public void TestBlockCount() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0,8), new StreamExtent(11, 4) }; Assert.AreEqual(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(0,8), new StreamExtent(9, 8) }; Assert.AreEqual(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; Assert.AreEqual(4, StreamExtent.BlockCount(s, 10)); }
public void TestBlocks() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0,8), new StreamExtent(11, 4) }; List<Range<long,long>> ranges = new List<Range<long,long>>(StreamExtent.Blocks(s, 10)); Assert.AreEqual(1, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(0,8), new StreamExtent(9, 8) }; ranges = new List<Range<long, long>>(StreamExtent.Blocks(s, 10)); Assert.AreEqual(1, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; ranges = new List<Range<long, long>>(StreamExtent.Blocks(s, 10)); Assert.AreEqual(2, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(3, ranges[0].Count); Assert.AreEqual(4, ranges[1].Offset); Assert.AreEqual(1, ranges[1].Count); }
public bool TryAllocate(long length, out long start) { if (length % Sizes.OneMiB != 0) { throw new ArgumentException("VHDX free space must be managed on 1MB boundaries", "length"); } for (int i = 0; i < _freeExtents.Count; ++i) { StreamExtent extent = _freeExtents[i]; if (extent.Length == length) { _freeExtents.RemoveAt(i); start = extent.Start; return true; } else if (extent.Length > length) { _freeExtents[i] = new StreamExtent(extent.Start + length, extent.Length - length); start = extent.Start; return true; } } start = 0; return false; }
public void TestIntersect4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,4)}; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3,8)}; StreamExtent[] s3 = new StreamExtent[] { new StreamExtent(10,10)}; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2, s3)); }
public override IEnumerable<StreamExtent> GetExtentsInRange(long start, long count) { StreamExtent lastRun = null; foreach (var block in _blocks) { if ((block.FirstSector + block.SectorCount) * Sizes.Sector < start) { // Skip blocks before start of range continue; } if (block.FirstSector * Sizes.Sector > start + count) { // Skip blocks after end of range continue; } foreach (var run in block.Runs) { if (run.SectorCount > 0 && run.Type != RunType.Zeros) { long thisRunStart = (block.FirstSector + run.SectorStart) * Sizes.Sector; long thisRunEnd = thisRunStart + (run.SectorCount * Sizes.Sector); thisRunStart = Math.Max(thisRunStart, start); thisRunEnd = Math.Min(thisRunEnd, start + count); long thisRunLength = thisRunEnd - thisRunStart; if (thisRunLength > 0) { if (lastRun != null && lastRun.Start + lastRun.Length == thisRunStart) { lastRun = new StreamExtent(lastRun.Start, lastRun.Length + thisRunLength); } else { if (lastRun != null) { yield return lastRun; } lastRun = new StreamExtent(thisRunStart, thisRunLength); } } } } } if (lastRun != null) { yield return lastRun; } }
public override IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { return(StreamExtent.Intersect(_attribute.RawBuffer.GetExtentsInRange(start, count), new StreamExtent(0, Capacity))); }
public void TestUnion4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,4), new StreamExtent(4,4)}; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0,8)}; Compare(r, StreamExtent.Union(s1)); }
public void TestUnion3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0,4)}; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(2,8)}; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0,10)}; Compare(r, StreamExtent.Union(s1, s2)); }