/// <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++; }
/// <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); }