diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2022-10-14 05:58:59 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-13 23:58:59 +0200 |
commit | be18f4e513799de186e6de53f32c9488b19f1ec7 (patch) | |
tree | a259966faef2cb66f5c070b06e5b396284993d35 /lib | |
parent | 6082b9ea5d4907e7ad8dfb66289d164a7cbdab42 (diff) | |
download | Nim-be18f4e513799de186e6de53f32c9488b19f1ec7.tar.gz |
follow up #19714; add `memmem` optimizations for `find` on Linux, Macos and BSDs (#20556)
* fixes tests * add memmem optimization for find * fixes * ty[o * fixes `"abc".find("") == 0 doesn't work on macOS Co-authored-by: xflywind <43030857+xflywind@users.noreply.github.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/strutils.nim | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index abdeed5b4..2e408f438 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1936,6 +1936,14 @@ func find*(s: string, chars: set[char], start: Natural = 0, last = -1): int {. if s[i] in chars: return i +when defined(linux): + proc memmem(haystack: pointer, haystacklen: csize_t, + needle: pointer, needlelen: csize_t): pointer {.importc, header: """#define _GNU_SOURCE +#include <string.h>""".} +elif defined(bsd) or (defined(macosx) and not defined(ios)): + proc memmem(haystack: pointer, haystacklen: csize_t, + needle: pointer, needlelen: csize_t): pointer {.importc, header: "#include <string.h>".} + func find*(s, sub: string, start: Natural = 0, last = -1): int {.rtl, extern: "nsuFindStr".} = ## Searches for `sub` in `s` inside range `start..last` (both ends included). @@ -1951,7 +1959,24 @@ func find*(s, sub: string, start: Natural = 0, last = -1): int {.rtl, if sub.len > s.len - start: return -1 if sub.len == 1: return find(s, sub[0], start, last) - result = find(initSkipTable(sub), s, sub, start, last) + template useSkipTable = + result = find(initSkipTable(sub), s, sub, start, last) + + when nimvm: + useSkipTable() + else: + when declared(memmem): + let subLen = sub.len + if last < 0 and start < s.len and subLen != 0: + let found = memmem(s[start].unsafeAddr, csize_t(s.len - start), sub.cstring, csize_t(subLen)) + result = if not found.isNil: + cast[ByteAddress](found) -% cast[ByteAddress](s.cstring) + else: + -1 + else: + useSkipTable() + else: + useSkipTable() func rfind*(s: string, sub: char, start: Natural = 0, last = -1): int {.rtl, extern: "nsuRFindChar".} = |