| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.Serialization;
- using System.Text;
- using System.ServiceModel;
- abstract class SequenceRangeCollection
- {
- static EmptyRangeCollection empty = new EmptyRangeCollection();
- static LowerComparer lowerComparer = new LowerComparer();
- static UpperComparer upperComparer = new UpperComparer();
- public abstract SequenceRange this[int index] { get; }
- public abstract int Count { get; }
- public static SequenceRangeCollection Empty
- {
- get
- {
- return empty;
- }
- }
- public abstract bool Contains(Int64 number);
- public abstract SequenceRangeCollection MergeWith(Int64 number);
- public abstract SequenceRangeCollection MergeWith(SequenceRange range);
- static SequenceRangeCollection GeneralCreate(SequenceRange[] sortedRanges)
- {
- if (sortedRanges.Length == 0)
- {
- return empty;
- }
- else if (sortedRanges.Length == 1)
- {
- return new SingleItemRangeCollection(sortedRanges[0]);
- }
- else
- {
- return new MultiItemRangeCollection(sortedRanges);
- }
- }
- static SequenceRangeCollection GeneralMerge(SequenceRange[] sortedRanges, SequenceRange range)
- {
- if (sortedRanges.Length == 0)
- {
- return new SingleItemRangeCollection(range);
- }
- int lowerBound;
- if (sortedRanges.Length == 1)
- {
- // Avoid performance hit of binary search in single range case
- if (range.Lower == sortedRanges[0].Upper)
- {
- lowerBound = 0;
- }
- else if (range.Lower < sortedRanges[0].Upper)
- {
- lowerBound = ~0;
- }
- else
- {
- lowerBound = ~1;
- }
- }
- else
- {
- lowerBound = Array.BinarySearch(sortedRanges, new SequenceRange(range.Lower), upperComparer);
- }
- if (lowerBound < 0)
- {
- lowerBound = ~lowerBound;
- if ((lowerBound > 0) && (sortedRanges[lowerBound - 1].Upper == range.Lower - 1))
- {
- lowerBound--;
- }
- if (lowerBound == sortedRanges.Length)
- {
- SequenceRange[] returnedRanges = new SequenceRange[sortedRanges.Length + 1];
- Array.Copy(sortedRanges, returnedRanges, sortedRanges.Length);
- returnedRanges[sortedRanges.Length] = range;
- return GeneralCreate(returnedRanges);
- }
- }
- int upperBound;
- if (sortedRanges.Length == 1)
- {
- // Avoid performance hit of binary search in single range case
- if (range.Upper == sortedRanges[0].Lower)
- {
- upperBound = 0;
- }
- else if (range.Upper < sortedRanges[0].Lower)
- {
- upperBound = ~0;
- }
- else
- {
- upperBound = ~1;
- }
- }
- else
- {
- upperBound = Array.BinarySearch(sortedRanges, new SequenceRange(range.Upper), lowerComparer);
- }
- if (upperBound < 0)
- {
- upperBound = ~upperBound;
- if (upperBound > 0)
- {
- if ((upperBound == sortedRanges.Length) || (sortedRanges[upperBound].Lower != range.Upper + 1))
- {
- upperBound--;
- }
- }
- else if (sortedRanges[0].Lower > range.Upper + 1)
- {
- SequenceRange[] returnedRanges = new SequenceRange[sortedRanges.Length + 1];
- Array.Copy(sortedRanges, 0, returnedRanges, 1, sortedRanges.Length);
- returnedRanges[0] = range;
- return GeneralCreate(returnedRanges);
- }
- }
- Int64 newLower = (range.Lower < sortedRanges[lowerBound].Lower) ? range.Lower : sortedRanges[lowerBound].Lower;
- Int64 newUpper = (range.Upper > sortedRanges[upperBound].Upper) ? range.Upper : sortedRanges[upperBound].Upper;
- int rangesRemoved = upperBound - lowerBound + 1;
- int rangesRemaining = sortedRanges.Length - rangesRemoved + 1;
- if (rangesRemaining == 1)
- {
- return new SingleItemRangeCollection(newLower, newUpper);
- }
- else
- {
- SequenceRange[] returnedRanges = new SequenceRange[rangesRemaining];
- Array.Copy(sortedRanges, returnedRanges, lowerBound);
- returnedRanges[lowerBound] = new SequenceRange(newLower, newUpper);
- Array.Copy(sortedRanges, upperBound + 1, returnedRanges, lowerBound + 1, sortedRanges.Length - upperBound - 1);
- return GeneralCreate(returnedRanges);
- }
- }
- public override string ToString()
- {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < Count; i++)
- {
- SequenceRange range = this[i];
- if (i > 0)
- {
- builder.Append(',');
- }
- builder.Append(range.Lower);
- builder.Append('-');
- builder.Append(range.Upper);
- }
- return builder.ToString();
- }
- class EmptyRangeCollection : SequenceRangeCollection
- {
- public override SequenceRange this[int index]
- {
- get
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- }
- }
- public override int Count
- {
- get
- {
- return 0;
- }
- }
- public override bool Contains(Int64 number)
- {
- return false;
- }
- public override SequenceRangeCollection MergeWith(Int64 number)
- {
- return new SingleItemRangeCollection(number, number);
- }
- public override SequenceRangeCollection MergeWith(SequenceRange range)
- {
- return new SingleItemRangeCollection(range);
- }
- }
- class MultiItemRangeCollection : SequenceRangeCollection
- {
- SequenceRange[] ranges;
- public MultiItemRangeCollection(SequenceRange[] sortedRanges)
- {
- this.ranges = sortedRanges;
- }
- public override SequenceRange this[int index]
- {
- get
- {
- if (index < 0 || index >= ranges.Length)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index", index,
- SR.GetString(SR.ValueMustBeInRange, 0, ranges.Length - 1)));
- return this.ranges[index];
- }
- }
- public override int Count
- {
- get
- {
- return this.ranges.Length;
- }
- }
- public override bool Contains(Int64 number)
- {
- if (this.ranges.Length == 0)
- {
- return false;
- }
- else if (this.ranges.Length == 1)
- {
- return this.ranges[0].Contains(number);
- }
- SequenceRange searchFor = new SequenceRange(number);
- int searchValue = Array.BinarySearch(this.ranges, searchFor, lowerComparer);
- if (searchValue >= 0)
- {
- return true;
- }
- searchValue = ~searchValue;
- if (searchValue == 0)
- {
- return false;
- }
- return (this.ranges[searchValue - 1].Upper >= number);
- }
- public override SequenceRangeCollection MergeWith(Int64 number)
- {
- return MergeWith(new SequenceRange(number));
- }
- public override SequenceRangeCollection MergeWith(SequenceRange newRange)
- {
- return GeneralMerge(this.ranges, newRange);
- }
- }
- class SingleItemRangeCollection : SequenceRangeCollection
- {
- SequenceRange range;
- public SingleItemRangeCollection(SequenceRange range)
- {
- this.range = range;
- }
- public SingleItemRangeCollection(Int64 lower, Int64 upper)
- {
- this.range = new SequenceRange(lower, upper);
- }
- public override SequenceRange this[int index]
- {
- get
- {
- if (index != 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
- return this.range;
- }
- }
- public override int Count
- {
- get
- {
- return 1;
- }
- }
- public override bool Contains(Int64 number)
- {
- return this.range.Contains(number);
- }
- public override SequenceRangeCollection MergeWith(Int64 number)
- {
- if (number == this.range.Upper + 1)
- {
- return new SingleItemRangeCollection(range.Lower, number);
- }
- else
- {
- return MergeWith(new SequenceRange(number));
- }
- }
- public override SequenceRangeCollection MergeWith(SequenceRange newRange)
- {
- if (newRange.Lower == this.range.Upper + 1)
- {
- return new SingleItemRangeCollection(range.Lower, newRange.Upper);
- }
- else if (this.range.Contains(newRange))
- {
- return this;
- }
- else if (newRange.Contains(this.range))
- {
- return new SingleItemRangeCollection(newRange);
- }
- else if (newRange.Upper == this.range.Lower - 1)
- {
- return new SingleItemRangeCollection(newRange.Lower, this.range.Upper);
- }
- else
- {
- return GeneralMerge(new SequenceRange[] { this.range }, newRange);
- }
- }
- }
- class LowerComparer : IComparer<SequenceRange>
- {
- public int Compare(SequenceRange x, SequenceRange y)
- {
- if (x.Lower < y.Lower)
- {
- return -1;
- }
- else if (x.Lower > y.Lower)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- }
- class UpperComparer : IComparer<SequenceRange>
- {
- public int Compare(SequenceRange x, SequenceRange y)
- {
- if (x.Upper < y.Upper)
- {
- return -1;
- }
- else if (x.Upper > y.Upper)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- }
- }
- }
|