mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 15:40:36 +03:00
Changed signature of findSkip, scheduled indexOf for deprecation, removed obsolete unittests
This commit is contained in:
parent
b2bf0bc48c
commit
c2f018066a
3 changed files with 70 additions and 71 deletions
121
std/algorithm.d
121
std/algorithm.d
|
@ -1328,7 +1328,7 @@ private:
|
||||||
{
|
{
|
||||||
static sizediff_t lastIndexOf(Range haystack, Separator needle)
|
static sizediff_t lastIndexOf(Range haystack, Separator needle)
|
||||||
{
|
{
|
||||||
immutable index = indexOf(retro(haystack), needle);
|
immutable index = countUntil(retro(haystack), needle);
|
||||||
return (index == -1) ? -1 : haystack.length - 1 - index;
|
return (index == -1) ? -1 : haystack.length - 1 - index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,7 +1359,7 @@ public:
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
if (_frontLength == _unComputed)
|
if (_frontLength == _unComputed)
|
||||||
{
|
{
|
||||||
_frontLength = indexOf(_input, _separator);
|
_frontLength = countUntil(_input, _separator);
|
||||||
if (_frontLength == -1) _frontLength = _input.length;
|
if (_frontLength == -1) _frontLength = _input.length;
|
||||||
}
|
}
|
||||||
return _input[0 .. _frontLength];
|
return _input[0 .. _frontLength];
|
||||||
|
@ -2833,36 +2833,37 @@ unittest
|
||||||
|
|
||||||
// findSkip
|
// findSkip
|
||||||
/**
|
/**
|
||||||
* Similar to $(D find), except returns the balance of $(D haystack)
|
* If $(D needle) occurs in $(D haystack), positions $(D haystack)
|
||||||
* just after the found range. If $(D needle) is not found, returns a
|
* right after the first occurrence of $(D needle) and returns $(D
|
||||||
* tuple with an empty range and $(D false). Otherwise, returns the
|
* true). Otherwise, leaves $(D haystack) as is and returns $(D
|
||||||
* portion of $(D haystack) starting right after the first occurrence
|
* false).
|
||||||
* of $(D needle).
|
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
----
|
----
|
||||||
assert(findSkip("abcdef", "cd").balance == "ef");
|
string s = "abcdef";
|
||||||
assert(findSkip("abcdef", "cxd").balance == null);
|
assert(findSkip("abcdef", "cd") && s == "ef");
|
||||||
assert(findSkip("abcdef", "cxd") == tuple("", false));
|
s = "abcdef";
|
||||||
|
assert(!findSkip("abcdef", "cxd") && s == "abcdef");
|
||||||
|
assert(findSkip("abcdef", "def") && s.empty);
|
||||||
----
|
----
|
||||||
*/
|
*/
|
||||||
Tuple!(R1, "balance", bool, "found")
|
bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle)
|
||||||
findSkip(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
|
||||||
if (isForwardRange!R1 && isForwardRange!R2
|
if (isForwardRange!R1 && isForwardRange!R2
|
||||||
&& is(typeof(binaryFun!pred(haystack.front, needle.front))))
|
&& is(typeof(binaryFun!pred(haystack.front, needle.front))))
|
||||||
{
|
{
|
||||||
static if (isSomeString!R1 && isSomeString!R2 || isRandomAccessRange!R1 && hasLength!R2)
|
static if (isSomeString!R1 && isSomeString!R2 || isRandomAccessRange!R1 && hasLength!R2)
|
||||||
{
|
{
|
||||||
haystack = find!pred(haystack, needle);
|
auto iter = find!pred(haystack, needle);
|
||||||
if (haystack.empty) return typeof(return)(haystack, false);
|
if (iter.empty) return false;
|
||||||
return typeof(return)(haystack[needle.length .. haystack.length], true);
|
haystack = iter[needle.length .. iter.length];
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (needle.empty)
|
if (needle.empty)
|
||||||
{
|
{
|
||||||
// The empty range is always found
|
// The empty range is always found
|
||||||
return typeof(return)(haystack, true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum estimateNeedleLength = hasLength!R1 && !hasLength!R2;
|
enum estimateNeedleLength = hasLength!R1 && !hasLength!R2;
|
||||||
|
@ -2875,11 +2876,11 @@ if (isForwardRange!R1 && isForwardRange!R2
|
||||||
immutable size_t estimatedNeedleLength = needle.length;
|
immutable size_t estimatedNeedleLength = needle.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool haystackTooShort()
|
bool haystackTooShort(R1 r)
|
||||||
{
|
{
|
||||||
static if (hasLength!R1)
|
static if (hasLength!R1)
|
||||||
{
|
{
|
||||||
return haystack.length < estimatedNeedleLength;
|
return r.length < estimatedNeedleLength;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2887,29 +2888,36 @@ if (isForwardRange!R1 && isForwardRange!R2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto iter = haystack.save;
|
||||||
searching:
|
searching:
|
||||||
for (;; haystack.popFront())
|
for (;; iter.popFront())
|
||||||
{
|
{
|
||||||
if (haystackTooShort())
|
if (haystackTooShort(iter))
|
||||||
{
|
{
|
||||||
// Failed search
|
// Failed search
|
||||||
static if (hasLength!R1)
|
static if (hasLength!R1)
|
||||||
{
|
{
|
||||||
static if (is(typeof(haystack[haystack.length ..
|
static if (is(typeof(iter[iter.length .. iter.length])
|
||||||
haystack.length]) : R1))
|
: R1))
|
||||||
return tuple(haystack[haystack.length .. haystack.length], false);
|
{
|
||||||
else
|
haystack = iter[iter.length .. iter.length];
|
||||||
return tuple(R1.init, false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(haystack.empty);
|
haystack = haystack.init;
|
||||||
return typeof(return)(haystack, false);
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(iter.empty);
|
||||||
|
haystack = iter;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static if (estimateNeedleLength)
|
static if (estimateNeedleLength)
|
||||||
size_t matchLength = 0;
|
size_t matchLength = 0;
|
||||||
auto h = haystack.save;
|
auto h = iter.save;
|
||||||
for (auto n = needle.save;
|
for (auto n = needle.save;
|
||||||
!n.empty;
|
!n.empty;
|
||||||
h.popFront(), n.popFront())
|
h.popFront(), n.popFront())
|
||||||
|
@ -2928,17 +2936,21 @@ if (isForwardRange!R1 && isForwardRange!R2
|
||||||
++matchLength;
|
++matchLength;
|
||||||
}
|
}
|
||||||
// Found
|
// Found
|
||||||
return typeof(return)(h, true);
|
haystack = h;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return typeof(return)(haystack, false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
assert(findSkip("abcdef", "cd").balance == "ef");
|
string s = "abcdef";
|
||||||
assert(findSkip("abcdef", "cxd").balance == null);
|
assert(findSkip(s, "cd") && s == "ef");
|
||||||
assert(findSkip("abcdef", "cxd") == tuple("", false));
|
s = "abcdef";
|
||||||
|
assert(!findSkip(s, "cxd") && s == "abcdef");
|
||||||
|
s = "abcdef";
|
||||||
|
assert(findSkip(s, "def") && s.empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2948,7 +2960,7 @@ returns the smallest $(D n) such that after $(D n) calls to $(D
|
||||||
haystack.popFront), $(D haystack.startsWith!pred(needle)). If no such
|
haystack.popFront), $(D haystack.startsWith!pred(needle)). If no such
|
||||||
number could be found, return $(D -1).
|
number could be found, return $(D -1).
|
||||||
*/
|
*/
|
||||||
sizediff_t indexOf(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
sizediff_t countUntil(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||||
if (is(typeof(startsWith!pred(haystack, needle))))
|
if (is(typeof(startsWith!pred(haystack, needle))))
|
||||||
{
|
{
|
||||||
static if (isNarrowString!R1)
|
static if (isNarrowString!R1)
|
||||||
|
@ -2974,6 +2986,19 @@ if (is(typeof(startsWith!pred(haystack, needle))))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as $(D countUntil). This symbol has been scheduled for
|
||||||
|
* deprecation because it is easily confused with the homonym function
|
||||||
|
* in $(D std.string).
|
||||||
|
*/
|
||||||
|
sizediff_t indexOf(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||||
|
if (is(typeof(startsWith!pred(haystack, needle))))
|
||||||
|
{
|
||||||
|
pragma(msg, "std.algorithm.indexOf has been scheduled for deprecation."
|
||||||
|
" You may want to use std.algorithm.countUntil instead.");
|
||||||
|
return countUntil!pred(haystack, needle);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Interval option specifier for $(D until) (below) and others.
|
Interval option specifier for $(D until) (below) and others.
|
||||||
*/
|
*/
|
||||||
|
@ -3633,11 +3658,8 @@ if (isInputRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack, n
|
||||||
{
|
{
|
||||||
enforce(!needle.empty, "Cannot count occurrences of an empty range");
|
enforce(!needle.empty, "Cannot count occurrences of an empty range");
|
||||||
size_t result;
|
size_t result;
|
||||||
for (;; ++result)
|
for (; findSkip!pred(haystack, needle); ++result)
|
||||||
{
|
{
|
||||||
auto r = findSkip!pred(haystack, needle);
|
|
||||||
if (!r.found) break;
|
|
||||||
haystack = r.balance;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -6474,11 +6496,6 @@ bool canFindSorted(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
return assumeSorted!pred(range).canFind!V(value);
|
return assumeSorted!pred(range).canFind!V(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
|
||||||
assert(canFindSorted([1,2,3,4,5], 4));
|
|
||||||
assert(!canFindSorted([1,2,3,4,5], 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scheduled for deprecation. Use std.range.SortedRange.lowerBound.
|
// Scheduled for deprecation. Use std.range.SortedRange.lowerBound.
|
||||||
Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
pragma(msg, "std.algorithm.lowerBound is scheduled for " ~
|
pragma(msg, "std.algorithm.lowerBound is scheduled for " ~
|
||||||
|
@ -6486,12 +6503,6 @@ Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
return assumeSorted!pred(range).lowerBound!V(value).release;
|
return assumeSorted!pred(range).lowerBound!V(value).release;
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
|
||||||
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
|
|
||||||
auto p = lowerBound!("a < b")(a, 4);
|
|
||||||
assert(equal(p, [0, 1, 2, 3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scheduled for deprecation. Use std.range.SortedRange.upperBound.
|
// Scheduled for deprecation. Use std.range.SortedRange.upperBound.
|
||||||
Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
pragma(msg, "std.algorithm.upperBound is scheduled for " ~
|
pragma(msg, "std.algorithm.upperBound is scheduled for " ~
|
||||||
|
@ -6499,12 +6510,6 @@ Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
return assumeSorted!pred(range).upperBound!V(value).release;
|
return assumeSorted!pred(range).upperBound!V(value).release;
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
|
||||||
int[] a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ];
|
|
||||||
auto p = upperBound(a, 3);
|
|
||||||
assert(equal(p, [4, 4, 5, 6 ]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scheduled for deprecation. Use std.range.SortedRange.equalRange.
|
// Scheduled for deprecation. Use std.range.SortedRange.equalRange.
|
||||||
Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
|
Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
pragma(msg, "std.algorithm.equalRange is scheduled for " ~
|
pragma(msg, "std.algorithm.equalRange is scheduled for " ~
|
||||||
|
@ -6512,12 +6517,6 @@ Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||||
return assumeSorted!pred(range).equalRange!V(value).release;
|
return assumeSorted!pred(range).equalRange!V(value).release;
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest {
|
|
||||||
auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ];
|
|
||||||
auto r = equalRange(a, 3);
|
|
||||||
assert(r == [ 3, 3, 3 ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Copies the top $(D n) elements of the input range $(D source) into the
|
Copies the top $(D n) elements of the input range $(D source) into the
|
||||||
random-access range $(D target), where $(D n =
|
random-access range $(D target), where $(D n =
|
||||||
|
|
|
@ -28642,7 +28642,7 @@ public:
|
||||||
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
||||||
//too inefficient to have to keep duping it every time we have to calculate the time.
|
//too inefficient to have to keep duping it every time we have to calculate the time.
|
||||||
//Hopefully, indexOf will properly support immutable ranges at some point.
|
//Hopefully, indexOf will properly support immutable ranges at some point.
|
||||||
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
||||||
|
|
||||||
if(found == -1)
|
if(found == -1)
|
||||||
return _transitions.back.ttInfo.isDST;
|
return _transitions.back.ttInfo.isDST;
|
||||||
|
@ -28678,7 +28678,7 @@ public:
|
||||||
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
||||||
//too inefficient to have to keep duping it every time we have to calculate the time.
|
//too inefficient to have to keep duping it every time we have to calculate the time.
|
||||||
//Hopefully, indexOf will properly support immutable ranges at some point.
|
//Hopefully, indexOf will properly support immutable ranges at some point.
|
||||||
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
||||||
|
|
||||||
if(found == -1)
|
if(found == -1)
|
||||||
return stdTime + convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
|
return stdTime + convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
|
||||||
|
@ -28715,7 +28715,7 @@ public:
|
||||||
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
||||||
//too inefficient to have to keep duping it every time we have to calculate the time.
|
//too inefficient to have to keep duping it every time we have to calculate the time.
|
||||||
//Hopefully, indexOf will properly support immutable ranges at some point.
|
//Hopefully, indexOf will properly support immutable ranges at some point.
|
||||||
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
|
||||||
|
|
||||||
if(found == -1)
|
if(found == -1)
|
||||||
return adjTime - convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
|
return adjTime - convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
|
||||||
|
@ -29668,7 +29668,7 @@ private:
|
||||||
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
|
||||||
//too inefficient to have to keep duping it every time we have to calculate the time.
|
//too inefficient to have to keep duping it every time we have to calculate the time.
|
||||||
//Hopefully, indexOf will properly support immutable ranges at some point.
|
//Hopefully, indexOf will properly support immutable ranges at some point.
|
||||||
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(LeapSecond[])_leapSeconds, unixTime);
|
auto found = std.algorithm.countUntil!"b < a.timeT"(cast(LeapSecond[])_leapSeconds, unixTime);
|
||||||
|
|
||||||
if(found == -1)
|
if(found == -1)
|
||||||
return _leapSeconds.back.total;
|
return _leapSeconds.back.total;
|
||||||
|
@ -31684,8 +31684,8 @@ bool validTimeUnits(string[] units...)
|
||||||
int cmpTimeUnits(string lhs, string rhs)
|
int cmpTimeUnits(string lhs, string rhs)
|
||||||
{
|
{
|
||||||
auto tstrings = timeStrings.dup;
|
auto tstrings = timeStrings.dup;
|
||||||
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
|
immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
|
||||||
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
|
immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
|
||||||
|
|
||||||
enforce(indexOfLHS != -1, format("%s is not a valid TimeString", lhs));
|
enforce(indexOfLHS != -1, format("%s is not a valid TimeString", lhs));
|
||||||
enforce(indexOfRHS != -1, format("%s is not a valid TimeString", rhs));
|
enforce(indexOfRHS != -1, format("%s is not a valid TimeString", rhs));
|
||||||
|
@ -31749,8 +31749,8 @@ template CmpTimeUnits(string lhs, string rhs)
|
||||||
private int cmpTimeUnitsCTFE(string lhs, string rhs)
|
private int cmpTimeUnitsCTFE(string lhs, string rhs)
|
||||||
{
|
{
|
||||||
auto tstrings = timeStrings.dup;
|
auto tstrings = timeStrings.dup;
|
||||||
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
|
immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
|
||||||
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
|
immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
|
||||||
|
|
||||||
if(indexOfLHS < indexOfRHS)
|
if(indexOfLHS < indexOfRHS)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -32763,7 +32763,7 @@ template nextSmallerTimeUnits(string units)
|
||||||
if(validTimeUnits(units) &&
|
if(validTimeUnits(units) &&
|
||||||
timeStrings.front != units)
|
timeStrings.front != units)
|
||||||
{
|
{
|
||||||
enum nextSmallerTimeUnits = timeStrings[std.algorithm.indexOf(timeStrings.dup, units) - 1];
|
enum nextSmallerTimeUnits = timeStrings[std.algorithm.countUntil(timeStrings.dup, units) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
@ -32800,7 +32800,7 @@ template nextLargerTimeUnits(string units)
|
||||||
if(validTimeUnits(units) &&
|
if(validTimeUnits(units) &&
|
||||||
timeStrings.back != units)
|
timeStrings.back != units)
|
||||||
{
|
{
|
||||||
enum nextLargerTimeUnits = timeStrings[std.algorithm.indexOf(timeStrings.dup, units) + 1];
|
enum nextLargerTimeUnits = timeStrings[std.algorithm.countUntil(timeStrings.dup, units) + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
|
|
@ -1438,7 +1438,7 @@ private string expandFromDatabase(string path)
|
||||||
|
|
||||||
// Extract username, searching for path separator.
|
// Extract username, searching for path separator.
|
||||||
string username;
|
string username;
|
||||||
auto last_char = std.algorithm.indexOf(path, sep[0]);
|
auto last_char = std.algorithm.countUntil(path, sep[0]);
|
||||||
|
|
||||||
if (last_char == -1)
|
if (last_char == -1)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue