mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 07:00:37 +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)
|
||||
{
|
||||
immutable index = indexOf(retro(haystack), needle);
|
||||
immutable index = countUntil(retro(haystack), needle);
|
||||
return (index == -1) ? -1 : haystack.length - 1 - index;
|
||||
}
|
||||
}
|
||||
|
@ -1359,7 +1359,7 @@ public:
|
|||
assert(!empty);
|
||||
if (_frontLength == _unComputed)
|
||||
{
|
||||
_frontLength = indexOf(_input, _separator);
|
||||
_frontLength = countUntil(_input, _separator);
|
||||
if (_frontLength == -1) _frontLength = _input.length;
|
||||
}
|
||||
return _input[0 .. _frontLength];
|
||||
|
@ -2833,36 +2833,37 @@ unittest
|
|||
|
||||
// findSkip
|
||||
/**
|
||||
* Similar to $(D find), except returns the balance of $(D haystack)
|
||||
* just after the found range. If $(D needle) is not found, returns a
|
||||
* tuple with an empty range and $(D false). Otherwise, returns the
|
||||
* portion of $(D haystack) starting right after the first occurrence
|
||||
* of $(D needle).
|
||||
* If $(D needle) occurs in $(D haystack), positions $(D haystack)
|
||||
* right after the first occurrence of $(D needle) and returns $(D
|
||||
* true). Otherwise, leaves $(D haystack) as is and returns $(D
|
||||
* false).
|
||||
*
|
||||
* Example:
|
||||
----
|
||||
assert(findSkip("abcdef", "cd").balance == "ef");
|
||||
assert(findSkip("abcdef", "cxd").balance == null);
|
||||
assert(findSkip("abcdef", "cxd") == tuple("", false));
|
||||
string s = "abcdef";
|
||||
assert(findSkip("abcdef", "cd") && s == "ef");
|
||||
s = "abcdef";
|
||||
assert(!findSkip("abcdef", "cxd") && s == "abcdef");
|
||||
assert(findSkip("abcdef", "def") && s.empty);
|
||||
----
|
||||
*/
|
||||
Tuple!(R1, "balance", bool, "found")
|
||||
findSkip(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2
|
||||
&& is(typeof(binaryFun!pred(haystack.front, needle.front))))
|
||||
{
|
||||
static if (isSomeString!R1 && isSomeString!R2 || isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
haystack = find!pred(haystack, needle);
|
||||
if (haystack.empty) return typeof(return)(haystack, false);
|
||||
return typeof(return)(haystack[needle.length .. haystack.length], true);
|
||||
auto iter = find!pred(haystack, needle);
|
||||
if (iter.empty) return false;
|
||||
haystack = iter[needle.length .. iter.length];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (needle.empty)
|
||||
{
|
||||
// The empty range is always found
|
||||
return typeof(return)(haystack, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
enum estimateNeedleLength = hasLength!R1 && !hasLength!R2;
|
||||
|
@ -2875,11 +2876,11 @@ if (isForwardRange!R1 && isForwardRange!R2
|
|||
immutable size_t estimatedNeedleLength = needle.length;
|
||||
}
|
||||
|
||||
bool haystackTooShort()
|
||||
bool haystackTooShort(R1 r)
|
||||
{
|
||||
static if (hasLength!R1)
|
||||
{
|
||||
return haystack.length < estimatedNeedleLength;
|
||||
return r.length < estimatedNeedleLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2887,29 +2888,36 @@ if (isForwardRange!R1 && isForwardRange!R2
|
|||
}
|
||||
}
|
||||
|
||||
auto iter = haystack.save;
|
||||
searching:
|
||||
for (;; haystack.popFront())
|
||||
for (;; iter.popFront())
|
||||
{
|
||||
if (haystackTooShort())
|
||||
if (haystackTooShort(iter))
|
||||
{
|
||||
// Failed search
|
||||
static if (hasLength!R1)
|
||||
{
|
||||
static if (is(typeof(haystack[haystack.length ..
|
||||
haystack.length]) : R1))
|
||||
return tuple(haystack[haystack.length .. haystack.length], false);
|
||||
else
|
||||
return tuple(R1.init, false);
|
||||
static if (is(typeof(iter[iter.length .. iter.length])
|
||||
: R1))
|
||||
{
|
||||
haystack = iter[iter.length .. iter.length];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(haystack.empty);
|
||||
return typeof(return)(haystack, false);
|
||||
haystack = haystack.init;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(iter.empty);
|
||||
haystack = iter;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static if (estimateNeedleLength)
|
||||
size_t matchLength = 0;
|
||||
auto h = haystack.save;
|
||||
auto h = iter.save;
|
||||
for (auto n = needle.save;
|
||||
!n.empty;
|
||||
h.popFront(), n.popFront())
|
||||
|
@ -2928,17 +2936,21 @@ if (isForwardRange!R1 && isForwardRange!R2
|
|||
++matchLength;
|
||||
}
|
||||
// Found
|
||||
return typeof(return)(h, true);
|
||||
haystack = h;
|
||||
return true;
|
||||
}
|
||||
return typeof(return)(haystack, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(findSkip("abcdef", "cd").balance == "ef");
|
||||
assert(findSkip("abcdef", "cxd").balance == null);
|
||||
assert(findSkip("abcdef", "cxd") == tuple("", false));
|
||||
string s = "abcdef";
|
||||
assert(findSkip(s, "cd") && s == "ef");
|
||||
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
|
||||
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))))
|
||||
{
|
||||
static if (isNarrowString!R1)
|
||||
|
@ -2974,6 +2986,19 @@ if (is(typeof(startsWith!pred(haystack, needle))))
|
|||
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.
|
||||
*/
|
||||
|
@ -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");
|
||||
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;
|
||||
}
|
||||
|
@ -6474,11 +6496,6 @@ bool canFindSorted(alias pred = "a < b", Range, V)(Range range, 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.
|
||||
Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
//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.
|
||||
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)
|
||||
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
|
||||
//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.
|
||||
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)
|
||||
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
|
||||
//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.
|
||||
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)
|
||||
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
|
||||
//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.
|
||||
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)
|
||||
return _leapSeconds.back.total;
|
||||
|
@ -31684,8 +31684,8 @@ bool validTimeUnits(string[] units...)
|
|||
int cmpTimeUnits(string lhs, string rhs)
|
||||
{
|
||||
auto tstrings = timeStrings.dup;
|
||||
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
|
||||
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
|
||||
immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
|
||||
immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
|
||||
|
||||
enforce(indexOfLHS != -1, format("%s is not a valid TimeString", lhs));
|
||||
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)
|
||||
{
|
||||
auto tstrings = timeStrings.dup;
|
||||
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
|
||||
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
|
||||
immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
|
||||
immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
|
||||
|
||||
if(indexOfLHS < indexOfRHS)
|
||||
return -1;
|
||||
|
@ -32763,7 +32763,7 @@ template nextSmallerTimeUnits(string units)
|
|||
if(validTimeUnits(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
|
||||
|
@ -32800,7 +32800,7 @@ template nextLargerTimeUnits(string units)
|
|||
if(validTimeUnits(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
|
||||
|
|
|
@ -1438,7 +1438,7 @@ private string expandFromDatabase(string path)
|
|||
|
||||
// Extract username, searching for path separator.
|
||||
string username;
|
||||
auto last_char = std.algorithm.indexOf(path, sep[0]);
|
||||
auto last_char = std.algorithm.countUntil(path, sep[0]);
|
||||
|
||||
if (last_char == -1)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue