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>
This commit is contained in:
ringabout
2022-10-14 05:58:59 +08:00
committed by GitHub
parent 6082b9ea5d
commit be18f4e513

View File

@@ -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".} =