strutils.find enhancements (#6582)
This commit is contained in:
parent
d2c7d391c8
commit
93fd0b0cb5
1 changed files with 48 additions and 26 deletions
|
|
@ -1330,18 +1330,36 @@ proc join*[T: not string](a: openArray[T], sep: string = ""): string {.
|
||||||
add(result, $x)
|
add(result, $x)
|
||||||
|
|
||||||
type
|
type
|
||||||
SkipTable = array[char, int]
|
SkipTable* = array[char, int]
|
||||||
|
|
||||||
{.push profiler: off.}
|
proc initSkipTable*(a: var SkipTable, sub: string)
|
||||||
proc preprocessSub(sub: string, a: var SkipTable) =
|
{.noSideEffect, rtl, extern: "nsuInitSkipTable".} =
|
||||||
var m = len(sub)
|
## Preprocess table `a` for `sub`.
|
||||||
for i in 0..0xff: a[chr(i)] = m+1
|
let m = len(sub)
|
||||||
for i in 0..m-1: a[sub[i]] = m-i
|
let m1 = m + 1
|
||||||
{.pop.}
|
var i = 0
|
||||||
|
while i <= 0xff-7:
|
||||||
|
a[chr(i + 0)] = m1
|
||||||
|
a[chr(i + 1)] = m1
|
||||||
|
a[chr(i + 2)] = m1
|
||||||
|
a[chr(i + 3)] = m1
|
||||||
|
a[chr(i + 4)] = m1
|
||||||
|
a[chr(i + 5)] = m1
|
||||||
|
a[chr(i + 6)] = m1
|
||||||
|
a[chr(i + 7)] = m1
|
||||||
|
i += 8
|
||||||
|
|
||||||
proc findAux(s, sub: string, start, last: int, a: SkipTable): int =
|
for i in 0..m-1:
|
||||||
# Fast "quick search" algorithm:
|
a[sub[i]] = m-i
|
||||||
var
|
|
||||||
|
proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last: Natural = 0): int
|
||||||
|
{.noSideEffect, 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`.
|
||||||
|
##
|
||||||
|
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||||
|
let
|
||||||
|
last = if last==0: s.high else: last
|
||||||
m = len(sub)
|
m = len(sub)
|
||||||
n = last + 1
|
n = last + 1
|
||||||
# search:
|
# search:
|
||||||
|
|
@ -1361,17 +1379,6 @@ when not (defined(js) or defined(nimdoc) or defined(nimscript)):
|
||||||
else:
|
else:
|
||||||
const hasCStringBuiltin = false
|
const hasCStringBuiltin = false
|
||||||
|
|
||||||
proc find*(s, sub: string, start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
|
||||||
rtl, extern: "nsuFindStr".} =
|
|
||||||
## Searches for `sub` in `s` inside range `start`..`last`.
|
|
||||||
## If `last` is unspecified, it defaults to `s.high`.
|
|
||||||
##
|
|
||||||
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
|
|
||||||
var a {.noinit.}: SkipTable
|
|
||||||
let last = if last==0: s.high else: last
|
|
||||||
preprocessSub(sub, a)
|
|
||||||
result = findAux(s, sub, start, last, a)
|
|
||||||
|
|
||||||
proc find*(s: string, sub: char, start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
proc find*(s: string, sub: char, start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
||||||
rtl, extern: "nsuFindChar".} =
|
rtl, extern: "nsuFindChar".} =
|
||||||
## Searches for `sub` in `s` inside range `start`..`last`.
|
## Searches for `sub` in `s` inside range `start`..`last`.
|
||||||
|
|
@ -1390,9 +1397,24 @@ proc find*(s: string, sub: char, start: Natural = 0, last: Natural = 0): int {.n
|
||||||
else:
|
else:
|
||||||
for i in start..last:
|
for i in start..last:
|
||||||
if sub == s[i]: return i
|
if sub == s[i]: return i
|
||||||
|
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
proc find*(s, sub: string, start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
||||||
|
rtl, extern: "nsuFindStr".} =
|
||||||
|
## Searches for `sub` in `s` inside range `start`..`last`.
|
||||||
|
## If `last` is unspecified, it defaults to `s.high`.
|
||||||
|
##
|
||||||
|
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||||
|
if sub.len > s.len:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if sub.len == 1:
|
||||||
|
return find(s, sub[0], start, last)
|
||||||
|
|
||||||
|
var a {.noinit.}: SkipTable
|
||||||
|
initSkipTable(a, sub)
|
||||||
|
result = find(a, s, sub, start, last)
|
||||||
|
|
||||||
proc find*(s: string, chars: set[char], start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
proc find*(s: string, chars: set[char], start: Natural = 0, last: Natural = 0): int {.noSideEffect,
|
||||||
rtl, extern: "nsuFindCharSet".} =
|
rtl, extern: "nsuFindCharSet".} =
|
||||||
## Searches for `chars` in `s` inside range `start`..`last`.
|
## Searches for `chars` in `s` inside range `start`..`last`.
|
||||||
|
|
@ -1524,11 +1546,11 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect,
|
||||||
## Replaces `sub` in `s` by the string `by`.
|
## Replaces `sub` in `s` by the string `by`.
|
||||||
var a {.noinit.}: SkipTable
|
var a {.noinit.}: SkipTable
|
||||||
result = ""
|
result = ""
|
||||||
preprocessSub(sub, a)
|
initSkipTable(a, sub)
|
||||||
let last = s.high
|
let last = s.high
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while true:
|
||||||
var j = findAux(s, sub, i, last, a)
|
var j = find(a, s, sub, i, last)
|
||||||
if j < 0: break
|
if j < 0: break
|
||||||
add result, substr(s, i, j - 1)
|
add result, substr(s, i, j - 1)
|
||||||
add result, by
|
add result, by
|
||||||
|
|
@ -1558,11 +1580,11 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
|
||||||
const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
|
const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
|
||||||
var a {.noinit.}: SkipTable
|
var a {.noinit.}: SkipTable
|
||||||
result = ""
|
result = ""
|
||||||
preprocessSub(sub, a)
|
initSkipTable(a, sub)
|
||||||
var i = 0
|
var i = 0
|
||||||
let last = s.high
|
let last = s.high
|
||||||
while true:
|
while true:
|
||||||
var j = findAux(s, sub, i, last, a)
|
var j = find(a, s, sub, i, last)
|
||||||
if j < 0: break
|
if j < 0: break
|
||||||
# word boundary?
|
# word boundary?
|
||||||
if (j == 0 or s[j-1] notin wordChars) and
|
if (j == 0 or s[j-1] notin wordChars) and
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue