Skip to content

Commit

Permalink
Changed API of string.find: before and after on a failed split are no…
Browse files Browse the repository at this point in the history
…w set as if the split occured at the end of the string.
  • Loading branch information
mleise committed Jul 4, 2013
1 parent 738b8f2 commit 25c0f3e
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 20 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
/.dub/
/obj/
fast
fast.dproj
fast.sln
/mono-d/

24 changes: 11 additions & 13 deletions source/fast/internal.d
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ version (benchmark)
import fast.string, fast.uniconv;

static immutable pathname = "hello/i_am_a/path_name\\with_several_different\\slashes";
static zeroterm = "wefwfnqwefnw(eknwoemkf)moorroijqwoijqioqo(vqwojkpjavnal(nvo(eirvn$wefwfnqwefnw(eknwoemkf)moorroijqwoijqioqo(vqwojkpjavnal(nvo(eirvn$wefwfnqwefnw(eknwoemkf)moorroijqwoijqioqo(vqwojkpjavnal(nvo(eirvn$\0";
static immutable zeroterm = "wefwfnqwefnw(eknwoemkf)moorroijqwoijq&oqo(vqwojkpjavnal(nvo(eirvn$wefwfnqwefnw(eknwoemkf)moorroijqwoihqioqo(vqwojkpjavnal(nvo(eirvn$wefwfnqwef\"w(eknwoemkf)moorroijqwoijqioqo(vqwojkpjavnal(nvo(eirvn$\0";
static pathSepRegex = ctRegex!`[/\\]`;
enum pathnameWStringLength = to!wstring(pathname).length;

Expand All @@ -189,24 +189,22 @@ version (benchmark)
benchmark ("uniconv.stackToWString", () { mixin stackToWString!("result", pathname); return result.ptr[pathnameWStringLength]; }),
);

run ("Check that there are no tabs in a string...", true,
benchmark ("std.string.indexOf", () { return std.string.indexOf(zeroterm, '\t') == -1; }),
benchmark ("algorithm.countUntil", () { return countUntil(zeroterm, '\t') == -1; }),
benchmark ("foreach", () { foreach (ref c; zeroterm) if (c == '\t') return false; return true; }),
benchmark ("fast.string.find", () { return !(fast.string.find!'\t'(zeroterm) < zeroterm.length); }),
run ("Split a string at each occurance of <, >, & and \"...", "w(eknwoemkf)moorroijqwoijqioqo(vqwojkpjavnal(nvo(eirvn$\0",
benchmark (`while + if with 4 cond`, () { string before; immutable(char*) stop = zeroterm.ptr + zeroterm.length; immutable(char)* iter = zeroterm.ptr; immutable(char)* done = zeroterm.ptr; if (iter !is stop) do { char c = *iter++; if (c == '<' || c == '>' || c == '&' || c == '"') { before = done[0 .. iter - done]; done = iter; }} while (iter !is stop); return done[0 .. stop - done]; }),
benchmark ("fast.string.find", () { string before, after = zeroterm; while (fast.string.split!('<', '>', '&', '"')(after, before, after)) {} return before; }),
);

run ("Find terminating zero in a string...", zeroterm.length - 1,
benchmark ("std.string.indexOf", () { return cast(size_t) std.string.indexOf(zeroterm, '\0'); }),
benchmark ("algorithm.countUntil", () { return cast(size_t) countUntil(zeroterm, '\0'); }),
benchmark ("while(*ptr) ptr++", () { auto ptr = zeroterm.ptr; while (*ptr) ptr++; return cast(size_t) (ptr - zeroterm.ptr); }),
benchmark ("fast.string.find", () { return fast.string.find!'\0'(zeroterm.ptr); }),
benchmark ("std.string.indexOf", () { return cast(size_t) std.string.indexOf(zeroterm, '\0'); }),
benchmark ("algorithm.countUntil", () { return cast(size_t) countUntil(zeroterm, '\0'); }),
benchmark ("while(*ptr) ptr++", () { auto ptr = zeroterm.ptr; while (*ptr) ptr++; return cast(size_t) (ptr - zeroterm.ptr); }),
benchmark ("fast.string.find", () { return fast.string.find!'\0'(zeroterm.ptr); }),
);

run ("Split a path by '/' or '\\'...", "slashes",
benchmark ("std.regex.splitter", () { string last; auto range = splitter(pathname, pathSepRegex); while (!range.empty) { last = range.front; range.popFront(); } return last; }),
benchmark ("std.regex.split", () { return split(pathname, pathSepRegex)[$-1]; }),
benchmark ("fast.string.split", () { string before, after = pathname; while (fast.string.split!('\\', '/')(after, before, after)) {} return after; }),
benchmark ("std.regex.splitter", () { string last; auto range = splitter(pathname, pathSepRegex); while (!range.empty) { last = range.front; range.popFront(); } return last; }),
benchmark ("std.regex.split", () { return split(pathname, pathSepRegex)[$-1]; }),
benchmark ("fast.string.split", () { string before, after = pathname; while (fast.string.split!('\\', '/')(after, before, after)) {} return before; }),
);

writeln("Benchmark done!");
Expand Down
11 changes: 6 additions & 5 deletions source/fast/string.d
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ import fast.internal;
* Splits a string in two around one or more compile-time known code units.
*
* Params:
* ch = The code unit(s) that initiates the split. It is typically an ASCII symbol.
* ch... = The code unit(s) that initiates the split. It is typically an ASCII symbol.
* str = The string to scan.
* before = Iff the call was successful, the part before the split is stored here. Otherwise it remains unchanged.
* after = Iff the call was successful, the part after the split is stored here. Otherwise it remains unchanged.
* before = The part before the split is stored here. If no character in $(D ch...) is found, the original string is returned here.
* after = The part after the split is stored here. If no character in $(D ch...) is found, $(D null) is returned here.
*
* Returns:
* $(D true), iff the symbol was found in the string.
*/
bool split(ch...)(scope inout(char[]) str, ref inout(char)[] before, ref inout(char)[] after, char* splitter = null)
{
immutable pos = findImpl!(false, ch)(str.ptr, str.length);
immutable pos = min (str.length, findImpl!(false, ch)(str.ptr, str.length));
before = str[0 .. pos];
if (pos < str.length) {
before = str[0 .. pos];
after = str[pos+1 .. $];
if (splitter) *splitter = str[pos];
return true;
}
after = null;
return false;
}

Expand Down

0 comments on commit 25c0f3e

Please sign in to comment.