mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 14:10:30 +03:00
std.string: Refactor indexOf to a per-CaseSensitive template
Use the same code for case sensitive and insensitive search, but refactor the case sensitivity parameter to a compile-time value under the hood, so that each instantiation receives its own propagated attributes.
This commit is contained in:
parent
a7485d9857
commit
606465af0b
1 changed files with 84 additions and 65 deletions
149
std/string.d
149
std/string.d
|
@ -756,6 +756,87 @@ if (isInputRange!Range && isSomeChar!(ElementType!Range))
|
|||
return -1;
|
||||
}
|
||||
|
||||
private template _indexOfStr(CaseSensitive cs)
|
||||
{
|
||||
private ptrdiff_t _indexOfStr(Range, Char)(Range s, const(Char)[] sub)
|
||||
if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) &&
|
||||
isSomeChar!Char)
|
||||
{
|
||||
alias Char1 = Unqual!(ElementEncodingType!Range);
|
||||
|
||||
static if (isSomeString!Range)
|
||||
{
|
||||
import std.algorithm.searching : find;
|
||||
|
||||
const(Char1)[] balance;
|
||||
static if (cs == Yes.caseSensitive)
|
||||
{
|
||||
balance = find(s, sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
balance = find!
|
||||
((a, b) => toLower(a) == toLower(b))
|
||||
(s, sub);
|
||||
}
|
||||
return () @trusted { return balance.empty ? -1 : balance.ptr - s.ptr; } ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.empty)
|
||||
return -1;
|
||||
if (sub.empty)
|
||||
return 0; // degenerate case
|
||||
|
||||
import std.utf : byDchar, codeLength;
|
||||
auto subr = sub.byDchar; // decode sub[] by dchar's
|
||||
dchar sub0 = subr.front; // cache first character of sub[]
|
||||
subr.popFront();
|
||||
|
||||
// Special case for single character search
|
||||
if (subr.empty)
|
||||
return indexOf(s, sub0, cs);
|
||||
|
||||
static if (cs == No.caseSensitive)
|
||||
sub0 = toLower(sub0);
|
||||
|
||||
/* Classic double nested loop search algorithm
|
||||
*/
|
||||
ptrdiff_t index = 0; // count code unit index into s
|
||||
for (auto sbydchar = s.byDchar(); !sbydchar.empty; sbydchar.popFront())
|
||||
{
|
||||
dchar c2 = sbydchar.front;
|
||||
static if (cs == No.caseSensitive)
|
||||
c2 = toLower(c2);
|
||||
if (c2 == sub0)
|
||||
{
|
||||
auto s2 = sbydchar.save; // why s must be a forward range
|
||||
foreach (c; subr.save)
|
||||
{
|
||||
s2.popFront();
|
||||
if (s2.empty)
|
||||
return -1;
|
||||
static if (cs == Yes.caseSensitive)
|
||||
{
|
||||
if (c != s2.front)
|
||||
goto Lnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toLower(c) != toLower(s2.front))
|
||||
goto Lnext;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
Lnext:
|
||||
index += codeLength!Char1(c2);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/++
|
||||
Searches for substring in `s`.
|
||||
|
||||
|
@ -787,72 +868,10 @@ ptrdiff_t indexOf(Range, Char)(Range s, const(Char)[] sub,
|
|||
if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) &&
|
||||
isSomeChar!Char)
|
||||
{
|
||||
alias Char1 = Unqual!(ElementEncodingType!Range);
|
||||
|
||||
static if (isSomeString!Range)
|
||||
{
|
||||
import std.algorithm.searching : find;
|
||||
|
||||
const(Char1)[] balance;
|
||||
if (cs == Yes.caseSensitive)
|
||||
{
|
||||
balance = find(s, sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
balance = find!
|
||||
((a, b) => toLower(a) == toLower(b))
|
||||
(s, sub);
|
||||
}
|
||||
return () @trusted { return balance.empty ? -1 : balance.ptr - s.ptr; } ();
|
||||
}
|
||||
if (cs == Yes.caseSensitive)
|
||||
return _indexOfStr!(Yes.caseSensitive)(s, sub);
|
||||
else
|
||||
{
|
||||
if (s.empty)
|
||||
return -1;
|
||||
if (sub.empty)
|
||||
return 0; // degenerate case
|
||||
|
||||
import std.utf : byDchar, codeLength;
|
||||
auto subr = sub.byDchar; // decode sub[] by dchar's
|
||||
dchar sub0 = subr.front; // cache first character of sub[]
|
||||
subr.popFront();
|
||||
|
||||
// Special case for single character search
|
||||
if (subr.empty)
|
||||
return indexOf(s, sub0, cs);
|
||||
|
||||
if (cs == No.caseSensitive)
|
||||
sub0 = toLower(sub0);
|
||||
|
||||
/* Classic double nested loop search algorithm
|
||||
*/
|
||||
ptrdiff_t index = 0; // count code unit index into s
|
||||
for (auto sbydchar = s.byDchar(); !sbydchar.empty; sbydchar.popFront())
|
||||
{
|
||||
dchar c2 = sbydchar.front;
|
||||
if (cs == No.caseSensitive)
|
||||
c2 = toLower(c2);
|
||||
if (c2 == sub0)
|
||||
{
|
||||
auto s2 = sbydchar.save; // why s must be a forward range
|
||||
foreach (c; subr.save)
|
||||
{
|
||||
s2.popFront();
|
||||
if (s2.empty)
|
||||
return -1;
|
||||
if (cs == Yes.caseSensitive ? c != s2.front
|
||||
: toLower(c) != toLower(s2.front)
|
||||
)
|
||||
goto Lnext;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
Lnext:
|
||||
index += codeLength!Char1(c2);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return _indexOfStr!(No.caseSensitive)(s, sub);
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue