Skip to content

Commit

Permalink
default last in strutils.find to -1
Browse files Browse the repository at this point in the history
  • Loading branch information
n5m committed Jun 4, 2021
1 parent 654a201 commit 3a99556
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 16 deletions.
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@

- `strformat` is now part of `include std/prelude`.

- Changed the behavior of passing `last=0` to any overload of `strutils.find`.
Previously, `last=0` indicated to search to the end of the string. Now,
`last=0` means "search as far as the 0th index of the string." Use `last = -1`
to use the old behavior. No change is required for invocations of
`strutils.find` where `last` is unspecified.

- Deprecated `proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T]` in `std/algorithm`.

- The configuration subsystem now allows for `-d:release` and `-d:danger` to work as expected.
Expand Down
30 changes: 18 additions & 12 deletions lib/pure/strutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1784,15 +1784,15 @@ 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 {.
func find*(a: SkipTable, s, sub: string, start: Natural = 0, last = -1): 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
## table `a`. If `last` is negative, it defaults to `s.high` (the last
## element).
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
let
last = if last == 0: s.high else: last
last = if last < 0: s.high else: last
subLast = sub.len - 1

if subLast == -1:
Expand Down Expand Up @@ -1823,10 +1823,10 @@ when not (defined(js) or defined(nimdoc) or defined(nimscript)):
else:
const hasCStringBuiltin = false

func find*(s: string, sub: char, start: Natural = 0, last = 0): int {.rtl,
func find*(s: string, sub: char, start: Natural = 0, last = -1): int {.rtl,
extern: "nsuFindChar".} =
## Searches for `sub` in `s` inside range `start..last` (both ends included).
## If `last` is unspecified, it defaults to `s.high` (the last element).
## If `last` is negative, it defaults to `s.high` (the last element).
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
## Otherwise the index returned is relative to `s[0]`, not `start`.
Expand All @@ -1835,7 +1835,7 @@ func find*(s: string, sub: char, start: Natural = 0, last = 0): int {.rtl,
## See also:
## * `rfind func<#rfind,string,char,Natural>`_
## * `replace func<#replace,string,char,char>`_
let last = if last == 0: s.high else: last
let last = if last < 0: s.high else: last
when nimvm:
for i in int(start)..last:
if sub == s[i]: return i
Expand All @@ -1851,10 +1851,10 @@ func find*(s: string, sub: char, start: Natural = 0, last = 0): int {.rtl,
if sub == s[i]: return i
return -1

func find*(s: string, chars: set[char], start: Natural = 0, last = 0): int {.
func find*(s: string, chars: set[char], start: Natural = 0, last = -1): int {.
rtl, extern: "nsuFindCharSet".} =
## Searches for `chars` in `s` inside range `start..last` (both ends included).
## If `last` is unspecified, it defaults to `s.high` (the last element).
## If `last` is negative, it defaults to `s.high` (the last element).
##
## If `s` contains none of the characters in `chars`, -1 is returned.
## Otherwise the index returned is relative to `s[0]`, not `start`.
Expand All @@ -1863,15 +1863,15 @@ func find*(s: string, chars: set[char], start: Natural = 0, last = 0): int {.
## See also:
## * `rfind func<#rfind,string,set[char],Natural>`_
## * `multiReplace func<#multiReplace,string,varargs[]>`_
let last = if last == 0: s.high else: last
let last = if last < 0: s.high else: last
for i in int(start)..last:
if s[i] in chars: return i
return -1

func find*(s, sub: string, start: Natural = 0, last = 0): int {.rtl,
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).
## If `last` is unspecified, it defaults to `s.high` (the last element).
## If `last` is negative, it defaults to `s.high` (the last element).
##
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
## Otherwise the index returned is relative to `s[0]`, not `start`.
Expand All @@ -1880,6 +1880,12 @@ func find*(s, sub: string, start: Natural = 0, last = 0): int {.rtl,
## See also:
## * `rfind func<#rfind,string,string,Natural>`_
## * `replace func<#replace,string,string,string>`_
runnableExamples:
doAssert find("abcbc", "") == 0
doAssert find("abcbc", "bc") == 1
doAssert find("abcbc", "bc", start=2) == 3
doAssert find("abcbc", "bc", last = 2) == 1
doAssert find("abcbc", "bc", last = 1) == -1
if sub.len > s.len - start: return -1
if sub.len == 1: return find(s, sub[0], start, last)

Expand All @@ -1895,7 +1901,7 @@ func find*(s, sub: string, start: Natural = 0, last = 0): int {.rtl,
useSkipTable()
else:
when hasCStringBuiltin:
if last == 0 and s.len > start:
if last < 0 and s.len > start:
let found = c_strstr(s[start].unsafeAddr, sub)
if not found.isNil:
result = cast[ByteAddress](found) -% cast[ByteAddress](s.cstring)
Expand Down
8 changes: 4 additions & 4 deletions tests/stdlib/tstrutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,15 @@ template main() =
# when last <= start, searching for non-empty string
block:
let last: int = -1
doAssert "abcd".find("ab", start=0, last=last) == -1
doAssert "abcd".find("ab", start=0, last=last) == 0
doAssert "abcd".find("ab", start=1, last=last) == -1
doAssert "abcd".find("bc", start=1, last=last) == -1
doAssert "abcd".find("bc", start=1, last=last) == 1
doAssert "abcd".find("bc", start=2, last=last) == -1
block:
let last: int = 0
doAssert "abcd".find("ab", start=0, last=last) == 0
doAssert "abcd".find("ab", start=0, last=last) == -1
doAssert "abcd".find("ab", start=1, last=last) == -1
doAssert "abcd".find("bc", start=1, last=last) == 1
doAssert "abcd".find("bc", start=1, last=last) == -1
doAssert "abcd".find("bc", start=2, last=last) == -1
block:
let last: int = 1
Expand Down

0 comments on commit 3a99556

Please sign in to comment.