Esempio n. 1
0
 // Constructor.
 public Enumerator(ListRangeView <T> view)
 {
     this.view  = view;
     this.index = view.startIndex - 1;
 }
Esempio n. 2
0
 public void Dispose()
 {
     this.view = null;
 }
Esempio n. 3
0
        /// <summary>
        /// Add elements to list.
        /// </summary>
        /// <param name="elements">Elements to add.</param>
        /// <param name="isSorted">Whether elements in <paramref name="elements"/> are already sorted or not.</param>
        public void AddAll(IEnumerable <T> elements, bool isSorted = false)
        {
            // sort elements
            var sortedElements = this.Sort(elements, isSorted);
            var elementCount   = sortedElements.Count;

            if (elementCount <= 0)
            {
                return;
            }
            if (elementCount == 1)
            {
                this.Add(sortedElements[0]);
                return;
            }

            // insert to tail of list
            var list     = this.list;
            var count    = list.Count;
            var comparer = this.comparer;

            if (count == 0 || comparer.Compare(sortedElements[0], list[count - 1]) >= 0)
            {
                list.AddRange(sortedElements);
                this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), count));
                return;
            }

            // insert to head of list
            if (comparer.Compare(sortedElements[elementCount - 1], list[0]) <= 0)
            {
                list.InsertRange(0, sortedElements);
                this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), 0));
                return;
            }

            // find insertion position
            var insertStartIndex = list.BinarySearch(sortedElements[0], comparer);
            var insertEndIndex   = list.BinarySearch(sortedElements[elementCount - 1], comparer);

            if (insertStartIndex < 0)
            {
                insertStartIndex = ~insertStartIndex;
            }
            if (insertEndIndex < 0)
            {
                insertEndIndex = ~insertEndIndex;
            }

            // insert to single position
            var insertionRegionSize = (insertEndIndex - insertStartIndex);

            if (insertionRegionSize < 0)
            {
                if (!this.IsSorted(comparer))
                {
                    throw new InternalStateCorruptedException();
                }
                throw new ArgumentException("Elements are not sorted properly.");
            }
            if (insertionRegionSize == 0)
            {
                list.InsertRange(insertStartIndex, sortedElements);
                this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), insertStartIndex));
                return;
            }

            // reserve space first
            if (list.Capacity < count + elementCount)
            {
                if (list.Capacity < int.MaxValue >> 1)
                {
                    list.Capacity = Math.Max(count << 1, count + (elementCount << 1));
                }
                else
                {
                    list.Capacity = count + (elementCount << 1);
                }
            }

            // insert by blocks
            var seStartIndex   = 0;
            var seIndex        = 0;
            var insertionCount = 0;

            while (seIndex < elementCount && insertStartIndex < count)
            {
                var seElement        = sortedElements[seIndex];
                var comparisonResult = comparer.Compare(seElement, list[insertStartIndex]);
                if (comparisonResult <= 0)
                {
                    ++seIndex;
                }
                else
                {
                    insertionCount = (seIndex - seStartIndex);
                    if (insertionCount == 1)
                    {
                        list.Insert(insertStartIndex, sortedElements[seStartIndex]);
                        this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, sortedElements[seStartIndex], insertStartIndex));
                        insertStartIndex += 2;
                        ++count;
                    }
                    else if (insertionCount > 0)
                    {
                        var insertionElements = new ListRangeView <T>(sortedElements, seStartIndex, insertionCount);
                        list.InsertRange(insertStartIndex, insertionElements);
                        this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, insertionElements, insertStartIndex));
                        insertStartIndex += insertionCount + 1;
                        count            += insertionCount;
                    }
                    else
                    {
                        ++insertStartIndex;
                    }
                    seStartIndex = seIndex;
                }
            }
            insertionCount = (elementCount - seStartIndex);
            if (insertionCount == 1)
            {
                list.Insert(insertStartIndex, sortedElements[seStartIndex]);
                this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, sortedElements[seStartIndex], insertStartIndex));
            }
            else if (insertionCount > 0)
            {
                var insertionElements = new ListRangeView <T>(sortedElements, seStartIndex, insertionCount);
                list.InsertRange(insertStartIndex, insertionElements);
                this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, insertionElements, insertStartIndex));
            }
        }