Consolidate overloads of copy()

This commit is contained in:
Andrei Alexandrescu 2019-03-27 22:28:59 -04:00
parent ba490f4d7b
commit 439b9a701b

View file

@ -366,58 +366,56 @@ Returns:
The unfilled part of target
*/
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
if (areCopyCompatibleArrays!(SourceRange, TargetRange))
if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange))
{
const tlen = target.length;
const slen = source.length;
assert(tlen >= slen,
"Cannot copy a source range into a smaller target range.");
immutable overlaps = __ctfe || () @trusted {
return source.ptr < target.ptr + tlen &&
target.ptr < source.ptr + slen; }();
if (overlaps)
static if (areCopyCompatibleArrays!(SourceRange, TargetRange))
{
foreach (idx; 0 .. slen)
target[idx] = source[idx];
return target[slen .. tlen];
const tlen = target.length;
const slen = source.length;
assert(tlen >= slen,
"Cannot copy a source range into a smaller target range.");
immutable overlaps = __ctfe || () @trusted {
return source.ptr < target.ptr + tlen &&
target.ptr < source.ptr + slen; }();
if (overlaps)
{
foreach (idx; 0 .. slen)
target[idx] = source[idx];
return target[slen .. tlen];
}
else
{
// Array specialization. This uses optimized memory copying
// routines under the hood and is about 10-20x faster than the
// generic implementation.
target[0 .. slen] = source[];
return target[slen .. $];
}
}
else
{
// Array specialization. This uses optimized memory copying
// routines under the hood and is about 10-20x faster than the
// generic implementation.
target[0 .. slen] = source[];
return target[slen .. $];
}
}
/// ditto
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
if (!areCopyCompatibleArrays!(SourceRange, TargetRange) &&
isInputRange!SourceRange &&
isOutputRange!(TargetRange, ElementType!SourceRange))
{
// Specialize for 2 random access ranges.
// Typically 2 random access ranges are faster iterated by common
// index than by x.popFront(), y.popFront() pair
static if (isRandomAccessRange!SourceRange &&
hasLength!SourceRange &&
hasSlicing!TargetRange &&
isRandomAccessRange!TargetRange &&
hasLength!TargetRange)
{
auto len = source.length;
foreach (idx; 0 .. len)
target[idx] = source[idx];
return target[len .. target.length];
}
else
{
foreach (element; source)
put(target, element);
return target;
// Specialize for 2 random access ranges.
// Typically 2 random access ranges are faster iterated by common
// index than by x.popFront(), y.popFront() pair
static if (isRandomAccessRange!SourceRange &&
hasLength!SourceRange &&
hasSlicing!TargetRange &&
isRandomAccessRange!TargetRange &&
hasLength!TargetRange)
{
auto len = source.length;
foreach (idx; 0 .. len)
target[idx] = source[idx];
return target[len .. target.length];
}
else
{
foreach (element; source)
put(target, element);
return target;
}
}
}