Skip to content

Commit

Permalink
add openArray variable of find with SkipTable
Browse files Browse the repository at this point in the history
  • Loading branch information
n5m committed Jun 20, 2021
1 parent 1788064 commit 58159fc
Showing 1 changed file with 63 additions and 7 deletions.
70 changes: 63 additions & 7 deletions lib/pure/strutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1784,15 +1784,26 @@ func initSkipTable*(a: var SkipTable, sub: string) {.rtl,
for i in 0 ..< m - 1:
a[sub[i]] = m - 1 - i

func find*(a: SkipTable, s, sub: string, start: Natural = 0, last = 0): int {.
rtl, extern: "nsuFindStrA".} =
## Searches for `sub` in `s` inside range `start..last` using preprocessed
## table `a`. If `last` is unspecified, it defaults to `s.high` (the last
## element).
func find*(a: SkipTable, s: openArray[char], sub: string): int =
## Searches for `sub` in `s` using preprocessed table `a`. Returns the
## leftmost index of `sub` in the slice if it is found. Othereise, returns -1.
## `sub` must be the same string that was used to initialize `a`.
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
## Searching is case-sensitive.
runnableExamples:
const haystack: string = "aabbccaadd"
const needle: string = "aa"
var a {.noinit.}: SkipTable
initSkipTable(a, needle)

doAssert find(a, haystack, needle) == 0
doAssert find(a, haystack.toOpenArray(0, 0), needle) == -1
doAssert find(a, haystack.toOpenArray(1, haystack.high), needle) == 5
doAssert find(a, haystack.toOpenArray(6, haystack.high), needle) == 0
doAssert find(a, haystack.toOpenArray(7, haystack.high), needle) == -1
let
last = if last == 0: s.high else: last
start = low(s)
last = high(s)
subLast = sub.len - 1

if subLast == -1:
Expand All @@ -1813,6 +1824,51 @@ func find*(a: SkipTable, s, sub: string, start: Natural = 0, last = 0): int {.
inc skip, a[s[skip + subLast]]
return -1

func find*(a: SkipTable, s, sub: string, start: Natural, last = 0): int {.
rtl, extern: "nsuFindStrA", deprecated: "use overload with openArray".} =
## Searches for `sub` in `s` inside range `start..last` using preprocessed
## table `a`. If `last` is unspecified, it defaults to `s.high` (the last
## element).
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. Use
## `the openArray variant<#find,SkipTable,openArray[char],string>`_. Note that
## this variant returns the index starting from the beginning of the string,
## whereas the non-deprecated variant returns the index starting from the
## beginning of the slice.
runnableExamples:
const haystack: string = "aabbccaadd"
const size: int = haystack.len
const needle: string = "aa"
var a {.noinit.}: SkipTable
initSkipTable(a, needle)

doAssert find(a, haystack, needle, start=0, last=size) == 0
# last=0 is treated as last=s.high, not as the 0-th index
doAssert find(a, haystack, needle, start=0, last=0) == 0
doAssert find(a, haystack, needle, start=1, last=size) == 6
doAssert find(a, haystack, needle, start=6, last=size) == 6
doAssert find(a, haystack, needle, start=7, last=size) == -1
if sub.len == 0:
return start
let last: int = if last == 0: s.high else: min(last, s.high)
if last < start:
return -1
let index: int = find(a, s[int(start)..last], sub)
if index == -1:
return -1
else:
# This version of find returns the index starting from the beginning of the
# string, but the openArray version of find returns the index starting from
# the beginning of the slice.
return start + index

func find*(a: SkipTable, s, sub: string, last: int): int {.
deprecated: "use overload with openArray".} =
## Exists for backwards compatibility for overloads with
## `find func<#find,SkipTable,string,string,Natural,int>`_ .
## Use `the openArray variant<#find,SkipTable,openArray[char],string>`_.
return find(a, s, sub, start = 0, last = last)

when not (defined(js) or defined(nimdoc) or defined(nimscript)):
func c_memchr(cstr: pointer, c: char, n: csize_t): pointer {.
importc: "memchr", header: "<string.h>".}
Expand Down

0 comments on commit 58159fc

Please sign in to comment.