Skip to content

Commit

Permalink
Complete the implementation of RangeCollection. Contains and Remove n…
Browse files Browse the repository at this point in the history
…ow work.

svn path=/trunk/bitsharp/; revision=123686
  • Loading branch information
alanmcgovern committed Jan 17, 2009
1 parent 3026b0a commit 17e7a20
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 38 deletions.
55 changes: 55 additions & 0 deletions src/MonoTorrent.Tests/Client/RangeCollectionTests.cs
Expand Up @@ -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");
}
}
}
10 changes: 10 additions & 0 deletions src/MonoTorrent/BanLists/BanList.cs
Expand Up @@ -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);
Expand Down
84 changes: 46 additions & 38 deletions src/MonoTorrent/BanLists/RangeCollection.cs
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}
}
}
}
Expand Down

0 comments on commit 17e7a20

Please sign in to comment.