예제 #1
0
        /// <summary>
        /// Inserts an element into the <see cref="BigArray{T}"/> at the specified index.
        /// </summary>
        /// <param name="index">Index of <see cref="BigArray{T}"/> where the value will be.</param>
        /// <param name="item">The data to be placed.</param>
        public void Insert(int index, T item)
        {
            if (index == Count)
            {
                Add(item);
                return;
            }

            var blockInfo = _arrayMap.BlockInfo(index);

            int blockSubindex = index - blockInfo.CommonStartIndex;
            int indexOfBlock  = blockInfo.IndexOfBlock;
            var block         = _blockCollection[blockInfo.IndexOfBlock];

            bool isMaxSize = (block.Count == _balancer.GetMaxBlockSize(indexOfBlock));
            bool isNeedToAddPreviosBlock = (blockSubindex == 0 && blockInfo.Count >= _balancer.GetDefaultBlockSize(indexOfBlock));

            if (isMaxSize)
            {
                _blockCollection.TryToDivideBlock(blockInfo.IndexOfBlock);
                _arrayMap.DataChanged(blockInfo.IndexOfBlock);
                Insert(index, item);
                return;
            }

            //Insertion
            if (!isNeedToAddPreviosBlock)
            {
                _blockCollection[blockInfo.IndexOfBlock].Insert(blockSubindex, item);
                _blockCollection.TryToDivideBlock(blockInfo.IndexOfBlock);
                _arrayMap.DataChanged(blockInfo.IndexOfBlock);
            }
            //Try to add to the previous block
            else
            {
                //If there is need - add new block
                bool isStartBlock    = (blockInfo.IndexOfBlock == 0);
                bool isPrevBlockFull = false;

                if (!isStartBlock)
                {
                    isPrevBlockFull = (_blockCollection[blockInfo.IndexOfBlock].Count == _balancer.GetMaxBlockSize(indexOfBlock));
                }

                if (isStartBlock || isPrevBlockFull)
                {
                    _blockCollection.InsertNewBlock(blockInfo.IndexOfBlock);

                    blockInfo.IndexOfBlock++;
                }

                _blockCollection[blockInfo.IndexOfBlock - 1].Add(item);
                _arrayMap.DataChanged(blockInfo.IndexOfBlock - 1);
            }

            Count++;
        }
예제 #2
0
        /// <summary>
        /// Divide specified block into several blocks(if it's needed) according to correspond default block sizes.
        /// </summary>
        /// <param name="collection">Collection, which must be divided.</param>
        /// <param name="collectionIndex">The zero-based starting index of the <see cref="collection"/> of elements to divide.</param>
        /// <param name="countToDivide">The number of elements of the <see cref="collection"/> to divide.</param>
        /// <returns>Collection of new blocks.</returns>
        private IList <Block <T> > DivideIntoBlocks(ICollection <T> collection, int collectionIndex, int countToDivide)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }

            if (!collection.IsValidRange(collectionIndex, countToDivide))
            {
                throw new ArgumentOutOfRangeException();
            }

            List <Block <T> > blockList = new List <Block <T> >();

            int alreadyProcessedCount = 0;

            var collectionEnumerator = collection.GetEnumerator();

            for (int i = 0; i < collectionIndex; i++) //Move item to the index position
            {
                collectionEnumerator.MoveNext();
            }

            for (int i = 0; alreadyProcessedCount != countToDivide; i++)
            {
                int currentBlockSize = _balancer.GetDefaultBlockSize(i);

                Block <T> newBlock = new Block <T>(currentBlockSize);
                blockList.Add(newBlock);

                currentBlockSize = Math.Min(currentBlockSize, countToDivide - alreadyProcessedCount);

                for (int j = 0; j < currentBlockSize; j++)
                {
                    collectionEnumerator.MoveNext();
                    newBlock.Add(collectionEnumerator.Current);
                }

                alreadyProcessedCount += currentBlockSize;
            }

            return(blockList);
        }