Ejemplo n.º 1
0
        /// <summary>
        /// Inserts the given <see cref="Array"/> within the given dimension and at the given position.
        /// </summary>
        /// <param name="arr"> An array to insert in the <see cref="DynamicArray{T}"/>.
        /// It must be not <see langword="null"/> and it must have a rank equal to <see cref="DynamicArray{T}.Rank"/>.
        /// </param>
        /// <param name="dimension"> The dimension where the elements of the <paramref name="arr"/> will be inserted.
        /// </param>
        /// <param name="indexes"> The position where the first element of the <paramref name="arr"/> will be inserted.
        /// </param>
        /// <exception cref="RankException"> If <paramref name="arr"/> has a rank not equal to
        /// <see cref="DynamicArray{T}.Rank"/>.</exception>
        /// <exception cref="ArgumentException"> If <paramref name="arr"/> has one of its lengths equal to zero.
        /// </exception>
        /// <exception cref="NullReferenceException"> If arr is <see langword="null"/></exception>
        public void Insert(Array arr, int dimension, params int[] indexes)
        {
            this.CheckIndexesLength(indexes);

            if (arr.Rank != this.Rank)
            {
                throw new RankException("Inserted array must have the same rank as this array");
            }

            for (int dim = 0; dim < this.Rank; ++dim)
            {
                if (arr.GetLength(dim) > 0)
                {
                    continue;
                }

                throw new ArgumentException("Inserted array must have non null lengths.", "arr");
            }

            int[] oldCounts = IndexesHelper.Clone(this.counts);
            int   dataCount = arr.GetLength(dimension);

            int[] lastIndices = IndexesHelper.Add(indexes, IndexesHelper.MaxIndexes(arr));
            lastIndices[dimension] = Math.Max(oldCounts[dimension], indexes[dimension]) + dataCount - 1;

            this.UpdateCountsAndCapacities(lastIndices);

            int[] rangeLowerBound = IndexesHelper.Add(indexes, -1);
            if (indexes[dimension] < oldCounts[dimension])
            {
                int[] rangeMax = IndexesHelper.Add(IndexesHelper.MaxIndexes(arr), indexes);
                rangeMax[dimension] = oldCounts[dimension] - 1;
                var rangeToMove = new IndexesEnumerator(rangeLowerBound, rangeMax, true);
                foreach (int[] source in rangeToMove)
                {
                    int[] destination = IndexesHelper.Clone(source);
                    destination[dimension] += dataCount;
                    this.buffer.SetValue(this.buffer.GetValue(source), destination);
                }
            }

            foreach (int[] source in IndexesEnumerator.Enumerate(arr))
            {
                int[] destination = IndexesHelper.Add(source, indexes);
                this.buffer.SetValue(arr.GetValue(source), destination);
            }

            ++this.changeCount;
        }