Changed signature of findSkip, scheduled indexOf for deprecation, removed obsolete unittests

This commit is contained in:
Andrei Alexandrescu 2011-01-17 08:36:59 +00:00
parent b2bf0bc48c
commit c2f018066a
3 changed files with 70 additions and 71 deletions

View file

@ -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 =

View file

@ -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

View file

@ -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)
{ {