From 17e7a202397a52de2d4f1e43092617b9fb156829 Mon Sep 17 00:00:00 2001 From: Alan McGovern Date: Sat, 17 Jan 2009 11:56:20 +0000 Subject: [PATCH] Complete the implementation of RangeCollection. Contains and Remove now work. svn path=/trunk/bitsharp/; revision=123686 --- .../Client/RangeCollectionTests.cs | 55 ++++++++++++ src/MonoTorrent/BanLists/BanList.cs | 10 +++ src/MonoTorrent/BanLists/RangeCollection.cs | 84 ++++++++++--------- 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/src/MonoTorrent.Tests/Client/RangeCollectionTests.cs b/src/MonoTorrent.Tests/Client/RangeCollectionTests.cs index a1bc3629e..cf976de58 100644 --- a/src/MonoTorrent.Tests/Client/RangeCollectionTests.cs +++ b/src/MonoTorrent.Tests/Client/RangeCollectionTests.cs @@ -82,5 +82,60 @@ public void AddTest3() Assert.AreEqual(2, ranges.Count, "#3"); Assert.AreEqual(new AddressRange(102, 700), ranges[1], "#3b"); } + + [Test] + public void ContainsTest() + { + RangeCollection c = new RangeCollection(); + c.Add(new AddressRange(1, 100)); + c.Add(new AddressRange(-10, -1)); + for (int i = -15; i < 120; i++) + { + bool shouldContain = (i >= -10 && i <= -1) || (i >= 1 && i <= 100); + Assert.AreEqual(shouldContain, c.Contains(new AddressRange(i, i)), "#1." + i); + } + } + + [Test] + public void RemoveTest() + { + RangeCollection c = new RangeCollection(); + c.Add(new AddressRange(0,100)); + c.Remove(new AddressRange(50, 50)); + Assert.AreEqual(2, c.Ranges.Count, "#1"); + Assert.AreEqual(new AddressRange(0, 49), c.Ranges[0], "#2"); + Assert.AreEqual(new AddressRange(51, 100), c.Ranges[1], "#3"); + + c.Remove(new AddressRange(50, 55)); + Assert.AreEqual(2, c.Ranges.Count, "#4"); + Assert.AreEqual(new AddressRange(0, 49), c.Ranges[0], "#5"); + Assert.AreEqual(new AddressRange(56, 100), c.Ranges[1], "#6"); + + c.Remove(new AddressRange(45, 60)); + Assert.AreEqual(2, c.Ranges.Count, "#7"); + Assert.AreEqual(new AddressRange(0, 44), c.Ranges[0], "#8"); + Assert.AreEqual(new AddressRange(61, 100), c.Ranges[1], "#9"); + + c.Remove(new AddressRange(45, 60)); + Assert.AreEqual(2, c.Ranges.Count, "#10"); + Assert.AreEqual(new AddressRange(0, 44), c.Ranges[0], "#11"); + Assert.AreEqual(new AddressRange(61, 100), c.Ranges[1], "#12"); + + c.Remove(new AddressRange(-100, 5)); + Assert.AreEqual(2, c.Ranges.Count, "#1"); + Assert.AreEqual(new AddressRange(6, 44), c.Ranges[0], "#1"); + Assert.AreEqual(new AddressRange(61, 100), c.Ranges[1], "#1"); + + c.Remove(new AddressRange(6, 15)); + Assert.AreEqual(2, c.Ranges.Count, "#1"); + Assert.AreEqual(new AddressRange(16, 44), c.Ranges[0], "#1"); + Assert.AreEqual(new AddressRange(61, 100), c.Ranges[1], "#1"); + + c.Remove(new AddressRange(70, 80)); + Assert.AreEqual(3, c.Ranges.Count, "#1"); + Assert.AreEqual(new AddressRange(16, 44), c.Ranges[0], "#1"); + Assert.AreEqual(new AddressRange(61,69), c.Ranges[1], "#1"); + Assert.AreEqual(new AddressRange(81, 100), c.Ranges[2], "#1"); + } } } diff --git a/src/MonoTorrent/BanLists/BanList.cs b/src/MonoTorrent/BanLists/BanList.cs index ae8efe24d..2db2d0981 100644 --- a/src/MonoTorrent/BanLists/BanList.cs +++ b/src/MonoTorrent/BanLists/BanList.cs @@ -50,6 +50,16 @@ public AddressRange(IPAddress start, IPAddress end) End = (IPAddress.NetworkToHostOrder(BitConverter.ToInt32(end.GetAddressBytes(), 0))); } + public bool Contains(int value) + { + return value >= Start && value <= End; + } + + public bool Contains(AddressRange range) + { + return range.Start >= Start && range.End <= End; + } + public override string ToString() { return string.Format("{0},{1}", Start, End); diff --git a/src/MonoTorrent/BanLists/RangeCollection.cs b/src/MonoTorrent/BanLists/RangeCollection.cs index b5713015a..7e760d943 100644 --- a/src/MonoTorrent/BanLists/RangeCollection.cs +++ b/src/MonoTorrent/BanLists/RangeCollection.cs @@ -109,7 +109,7 @@ bool MergeLeft(AddressRange range, int position) if (ranges.Count > position && position >= 0) { AddressRange leftRange = ranges[position]; - if (range.Start >= leftRange.Start && range.Start <= leftRange.End) + if (leftRange.Contains(range.Start)) { ranges[position] = new AddressRange(leftRange.Start, Math.Max(leftRange.End, range.End)); return true; @@ -135,17 +135,17 @@ bool MergeRight(AddressRange range, int position) if (position >= 0 && position < ranges.Count) { AddressRange rightRange = ranges[position]; - if (range.End <= rightRange.End && range.End >= rightRange.Start) + if (rightRange.Contains(range.End)) { ranges[position] = new AddressRange(Math.Min(range.Start, rightRange.Start), rightRange.End); return true; } - else if (range.Start <= rightRange.Start && range.End >= rightRange.Start) + else if (range.Contains(rightRange)) { ranges[position] = range; return true; } - else if (range.Start >= rightRange.Start && range.Start <= rightRange.End) + else if (rightRange.Contains(range.Start)) { ranges[position] = new AddressRange(rightRange.Start, Math.Max(range.End, rightRange.End)); return true; @@ -156,54 +156,62 @@ bool MergeRight(AddressRange range, int position) internal bool Contains(AddressRange range) { - int index = ranges.BinarySearch(range); - if (index > 0) - return true; - index = ~index; - if (index >= ranges.Count) + int index = ranges.BinarySearch(range, new RangeComparer()); + + // The start of this range is smaller than the start of any range in the list + if (index == -1) return false; - AddressRange r = ranges[index]; - return range.Start >= r.Start && range.Start <= r.End; + // An element in the collection has the same 'Start' as 'range' + if (index >= 0) + return range.End <= ranges[index].End; + + index = ~index; + AddressRange r = ranges[index - 1]; + return r.Contains(range); } - internal void Remove(AddressRange addressRange) + internal void Remove(AddressRange item) { if (ranges.Count == 0) return; - int index = ranges.BinarySearch(addressRange, new RangeComparer()); - if (index < 0) + for (int i = item.Start; i <= item.End; i++) { - index = Math.Max((~index) - 1, 0); + AddressRange addressRange = new AddressRange(i, i); + int index = ranges.BinarySearch(addressRange, new RangeComparer()); + if (index < 0) + { + index = Math.Max((~index) - 1, 0); - AddressRange range = ranges[index]; - if (addressRange.Start < range.Start || addressRange.Start > range.End) - return; + AddressRange range = ranges[index]; + if (addressRange.Start < range.Start || addressRange.Start > range.End) + continue; - if (addressRange.Start == range.Start) - { - ranges[index] = new AddressRange(range.Start + 1, range.End); - } - else if (addressRange.End == range.End) - { - ranges[index] = new AddressRange(range.Start, range.End - 1); + if (addressRange.Start == range.Start) + { + ranges[index] = new AddressRange(range.Start + 1, range.End); + } + else if (addressRange.End == range.End) + { + ranges[index] = new AddressRange(range.Start, range.End - 1); + } + else + { + ranges[index] = new AddressRange(range.Start, addressRange.Start - 1); + ranges.Insert(index + 1, new AddressRange(addressRange.Start + 1, range.End)); + } } else { - ranges[index] = new AddressRange(range.Start, addressRange.Start - 1); - ranges.Insert(index+1, new AddressRange(addressRange.Start + 1, range.End)); - } - } - else - { - AddressRange range = ranges[index]; - if (addressRange.Start >= range.Start && addressRange.End <= range.End) - { - if (range.Start == range.End) - ranges.RemoveAt(index); - else - ranges[index] = new AddressRange(range.Start + 1, range.End); + AddressRange range = ranges[index]; + if (range.Contains(addressRange)) + { + if (range.Start == range.End) + ranges.RemoveAt(index); + else + ranges[index] = new AddressRange(range.Start + 1, range.End); + } } } }