예제 #1
0
        /// <summary>
        /// Finds the range that contains "val", or an appropriate place in the list to
        /// insert a new range.
        /// </summary>
        /// <param name="val">Value to find.</param>
        /// <returns>The index of the matching element, or a negative value indicating
        /// the index to insert at.  2C doesn't support negative 0, so the insertion
        /// index will be incremented before negation.</returns>
        private int FindValue(int val)
        {
            int low  = 0;
            int high = mRangeList.Count - 1;

            while (low <= high)
            {
                int        mid      = (low + high) / 2;
                TypedRange midRange = mRangeList[mid];

                if (midRange.Contains(val))
                {
                    // found it
                    return(mid);
                }
                else if (val < midRange.Low)
                {
                    // too big, move the high end in
                    high = mid - 1;
                }
                else if (val > midRange.High)
                {
                    // too small, move the low end in
                    low = mid + 1;
                }
                else
                {
                    // WTF... list not sorted?
                    throw new Exception("Bad binary search");
                }
            }

            // Not found, insert before "low".
            return(-(low + 1));
        }
예제 #2
0
        /// <summary>
        /// Finds a range that contains searchVal, or identifies the one that immediately
        /// follows.  The caller can determine which by checking to see if range.Low is
        /// greater than searchVal.
        /// </summary>
        /// <param name="searchVal">Value to find.</param>
        /// <param name="range">Result.</param>
        /// <returns>True if a valid range was returned.</returns>
        public bool GetContainingOrSubsequentRange(int searchVal, out TypedRange range)
        {
            int index = FindValue(searchVal);

            if (index >= 0)
            {
                // found a range that contains val
                range = mRangeList[index];
                return(true);
            }

            // No matching range, so the index of the insertion point was returned.  The
            // indexed range will have a "low" value that is greater than searchVal.  If
            // we've reached the end of the list, the index will be past the end.
            index = -index - 1;
            if (index >= mRangeList.Count)
            {
                // reached the end of the list
                range = new TypedRange(-128, -128, -128);
                return(false);
            }

            range = mRangeList[index];
            return(true);
        }
예제 #3
0
        public void DebugDump(string name)
        {
            Debug.WriteLine(name + " has " + RangeCount + " ranges");
            IEnumerator <TypedRange> iter = RangeListIterator;

            while (iter.MoveNext())
            {
                TypedRange rng = iter.Current;
                Debug.WriteLine("[+{0:x6},+{1:x6}] ({2:x2})", rng.Low, rng.High, rng.Type);
            }
        }
예제 #4
0
            /// <summary>
            /// Puts the next range in the list in mCurrentRange.
            /// </summary>
            /// <returns>True on success, false if we reached the end of the list.</returns>
            private bool GetNextRange()
            {
                mListIndex++;   // increments to 0 on first invocation
                if (mListIndex == mSet.mRangeList.Count)
                {
                    // no more ranges
                    return(false);
                }

                mCurrentRange = mSet.mRangeList[mListIndex];
                mCurrentVal   = mCurrentRange.Low;
                return(true);
            }
예제 #5
0
        /// <summary>
        /// Removes a value from the set.  If the value is not present, nothing changes.
        /// </summary>
        /// <param name="val">Value to remove.</param>
        public void Remove(int val)
        {
            int listIndex = FindValue(val);

            if (listIndex < 0)
            {
                // not found
                return;
            }

            Count--;

            TypedRange rng = mRangeList[listIndex];

            if (rng.Low == val && rng.High == val)
            {
                // Single-value range.  Remove.
                mRangeList.RemoveAt(listIndex);
            }
            else if (rng.Low == val)
            {
                // We're at the low end, reduce range.
                rng.Low = val + 1;
                mRangeList[listIndex] = rng;
            }
            else if (rng.High == val)
            {
                // We're at the high end, reduce range.
                rng.High = val - 1;
                mRangeList[listIndex] = rng;
            }
            else
            {
                // We're in the middle, split the range.
                TypedRange next = new TypedRange(val + 1, rng.High, rng.Type);
                rng.High = val - 1;
                mRangeList[listIndex] = rng;
                mRangeList.Insert(listIndex + 1, next);
            }
        }
예제 #6
0
        /// <summary>
        /// Adds or changes a value to the set.  If the value is already present and has
        /// a matching type, nothing changes.
        /// </summary>
        /// <param name="val">Value to add.</param>
        /// <param name="type">Value's type.</param>
        public void Add(int val, int type)
        {
            int listIndex = FindValue(val);

            if (listIndex >= 0)
            {
                // Value is present in set, check type.
                if (mRangeList[listIndex].Type == type)
                {
                    // It's a match, do nothing.
                    return;
                }

                // Wrong type. Remove previous entry, then fall through to add new.
                Remove(val);
                listIndex = FindValue(val);     // get insertion point
            }
            Count++;

            if (mRangeList.Count == 0)
            {
                // Empty list, skip the gymnastics.
                mRangeList.Add(new TypedRange(val, val, type));
                return;
            }

            // Negate and decrement to get insertion index.  This value may == Count if
            // the value is higher than all current members.
            listIndex = -listIndex - 1;

            if (listIndex > 0 && mRangeList[listIndex - 1].High == val - 1 &&
                mRangeList[listIndex - 1].Type == type)
            {
                // Expand prior range.  Check to see if it blends into next as well.
                if (listIndex < mRangeList.Count && mRangeList[listIndex].Low == val + 1 &&
                    mRangeList[listIndex].Type == type)
                {
                    // Combine ranges.
                    TypedRange prior = mRangeList[listIndex - 1];
                    TypedRange next  = mRangeList[listIndex];
                    Debug.Assert(prior.High + 2 == next.Low);
                    prior.High = next.High;
                    mRangeList[listIndex - 1] = prior;
                    mRangeList.RemoveAt(listIndex);
                }
                else
                {
                    // Nope, just expand the prior range.
                    TypedRange prior = mRangeList[listIndex - 1];
                    Debug.Assert(prior.High == val - 1);
                    prior.High = val;
                    mRangeList[listIndex - 1] = prior;
                }
            }
            else if (listIndex < mRangeList.Count && mRangeList[listIndex].Low == val + 1 &&
                     mRangeList[listIndex].Type == type)
            {
                // Expand next range.
                TypedRange next = mRangeList[listIndex];
                Debug.Assert(next.Low == val + 1);
                next.Low = val;
                mRangeList[listIndex] = next;
            }
            else
            {
                // Nothing adjacent, add a new single-entry element.
                mRangeList.Insert(listIndex, new TypedRange(val, val, type));
            }
        }
예제 #7
0
 public TypedRangeEnumerator(TypedRange owner)
 {
     this.owner = owner;
     Reset();
 }