Skip to content

Commit cc39281

Browse files
authored
Merge pull request scala/scala#10691 from som-snytt/issue/12948-copy-array
IterableOnce#copyToArray uses helper for count [ci: last-only]
2 parents 0fa1f2e + 6dde5b0 commit cc39281

File tree

1 file changed

+47
-24
lines changed

1 file changed

+47
-24
lines changed

library/src/scala/collection/IterableOnce.scala

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import scala.math.{Numeric, Ordering}
2121
import scala.reflect.ClassTag
2222
import scala.runtime.{AbstractFunction1, AbstractFunction2}
2323

24+
import IterableOnce.elemsToCopyToArray
25+
2426
/**
2527
* A template trait for collections which can be traversed either once only
2628
* or one or more times.
@@ -264,16 +266,25 @@ object IterableOnce {
264266
@inline implicit def iterableOnceExtensionMethods[A](it: IterableOnce[A]): IterableOnceExtensionMethods[A] =
265267
new IterableOnceExtensionMethods[A](it)
266268

267-
/** Computes the number of elements to copy to an array from a source IterableOnce
268-
*
269-
* @param srcLen the length of the source collection
270-
* @param destLen the length of the destination array
271-
* @param start the index in the destination array at which to start copying elements to
272-
* @param len the requested number of elements to copy (we may only be able to copy less than this)
273-
* @return the number of elements that will be copied to the destination array
274-
*/
275-
@inline private[collection] def elemsToCopyToArray(srcLen: Int, destLen: Int, start: Int, len: Int): Int =
276-
math.max(math.min(math.min(len, srcLen), destLen - start), 0)
269+
/** Computes the number of elements to copy to an array from a source IterableOnce.
270+
*
271+
* If `start` is less than zero, it is taken as zero.
272+
* If any of the length inputs is less than zero, the computed result is zero.
273+
*
274+
* The result is the smaller of the remaining capacity in the destination and the requested count.
275+
*
276+
* @param srcLen the length of the source collection
277+
* @param destLen the length of the destination array
278+
* @param start the index in the destination array at which to start copying elements
279+
* @param len the requested number of elements to copy (we may only be able to copy less than this)
280+
* @return the number of elements that will be copied to the destination array
281+
*/
282+
@inline private[collection] def elemsToCopyToArray(srcLen: Int, destLen: Int, start: Int, len: Int): Int = {
283+
val limit = math.min(len, srcLen)
284+
val capacity = if (start < 0) destLen else destLen - start
285+
val total = math.min(capacity, limit)
286+
math.max(0, total)
287+
}
277288

278289
/** Calls `copyToArray` on the given collection, regardless of whether or not it is an `Iterable`. */
279290
@inline private[collection] def copyElemsToArray[A, B >: A](elems: IterableOnce[A],
@@ -986,58 +997,70 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
986997

987998
/** Copies elements to an array, returning the number of elements written.
988999
*
989-
* Fills the given array `xs` starting at index `start` with values of this $coll.
1000+
* Fills the given array `dest` starting at index `start` with values of this $coll.
9901001
*
9911002
* Copying will stop once either all the elements of this $coll have been copied,
9921003
* or the end of the array is reached.
9931004
*
994-
* @param xs the array to fill.
1005+
* @param dest the array to fill.
9951006
* @tparam B the type of the elements of the array.
9961007
* @return the number of elements written to the array
9971008
*
9981009
* @note Reuse: $consumesIterator
9991010
*/
10001011
@deprecatedOverriding("This should always forward to the 3-arg version of this method", since = "2.13.4")
1001-
def copyToArray[B >: A](xs: Array[B]): Int = copyToArray(xs, 0, Int.MaxValue)
1012+
def copyToArray[B >: A](@deprecatedName("xs", since="2.13.17") dest: Array[B]): Int =
1013+
copyToArray(dest, start = 0, n = Int.MaxValue)
10021014

10031015
/** Copies elements to an array, returning the number of elements written.
10041016
*
1005-
* Fills the given array `xs` starting at index `start` with values of this $coll.
1017+
* Fills the given array `dest` starting at index `start` with values of this $coll.
10061018
*
10071019
* Copying will stop once either all the elements of this $coll have been copied,
10081020
* or the end of the array is reached.
10091021
*
1010-
* @param xs the array to fill.
1022+
* @param dest the array to fill.
10111023
* @param start the starting index of xs.
10121024
* @tparam B the type of the elements of the array.
10131025
* @return the number of elements written to the array
10141026
*
10151027
* @note Reuse: $consumesIterator
10161028
*/
10171029
@deprecatedOverriding("This should always forward to the 3-arg version of this method", since = "2.13.4")
1018-
def copyToArray[B >: A](xs: Array[B], start: Int): Int = copyToArray(xs, start, Int.MaxValue)
1030+
def copyToArray[B >: A](@deprecatedName("xs", since="2.13.17") dest: Array[B], start: Int): Int =
1031+
copyToArray(dest, start = start, n = Int.MaxValue)
10191032

1020-
/** Copy elements to an array, returning the number of elements written.
1033+
/** Copies elements to an array and returns the number of elements written.
10211034
*
1022-
* Fills the given array `xs` starting at index `start` with at most `len` elements of this $coll.
1035+
* Fills the given array `dest` starting at index `start` with at most `n` elements of this $coll.
10231036
*
10241037
* Copying will stop once either all the elements of this $coll have been copied,
1025-
* or the end of the array is reached, or `len` elements have been copied.
1038+
* or the end of the array is reached, or `n` elements have been copied.
10261039
*
1027-
* @param xs the array to fill.
1040+
* If `start` is less than zero, it is taken as zero.
1041+
*
1042+
* @param dest the array to fill.
10281043
* @param start the starting index of xs.
1029-
* @param len the maximal number of elements to copy.
1044+
* @param n the maximal number of elements to copy.
10301045
* @tparam B the type of the elements of the array.
10311046
* @return the number of elements written to the array
10321047
*
10331048
* @note Reuse: $consumesIterator
10341049
*/
1035-
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = {
1050+
def copyToArray[B >: A](
1051+
@deprecatedName("xs", since="2.13.17") dest: Array[B],
1052+
start: Int,
1053+
@deprecatedName("len", since="2.13.17") n: Int
1054+
): Int = {
10361055
val it = iterator
10371056
var i = start
1038-
val end = start + math.min(len, xs.length - start)
1057+
val srclen = knownSize match {
1058+
case -1 => dest.length
1059+
case k => k
1060+
}
1061+
val end = start + elemsToCopyToArray(srclen, dest.length, start, n)
10391062
while (i < end && it.hasNext) {
1040-
xs(i) = it.next()
1063+
dest(i) = it.next()
10411064
i += 1
10421065
}
10431066
i - start

0 commit comments

Comments
 (0)