Add replace

Also came a cross a find bug with 0-length subject strings
This commit is contained in:
Flaviu Tamas
2015-01-17 16:21:25 -05:00
parent a7ce05b42f
commit 4d25a89ba9
4 changed files with 34 additions and 5 deletions

View File

@@ -329,11 +329,7 @@ iterator findIter*(str: string, pattern: Regex, start = 0, endpos = -1): RegexMa
var offset = start
var previousMatch: RegexMatch
while offset != endpos:
if offset > endpos:
# eos occurs in the middle of a unicode char? die.
raise newException(AssertionError, "Input string has malformed unicode")
while true:
var flags = 0
if previousMatch != nil and
@@ -356,11 +352,16 @@ iterator findIter*(str: string, pattern: Regex, start = 0, endpos = -1): RegexMa
elif unicode:
# XXX what about invalid unicode?
offset += str.runeLenAt(offset)
assert(offset <= endpos)
else:
offset = currentMatch.matchBounds.b
yield currentMatch
if offset >= endpos:
# do while
break
proc find*(str: string, pattern: Regex, start = 0, endpos = -1): RegexMatch =
## Returns a `RegexMatch` if there is a match between `start` and `endpos`, otherwise
## it returns nil.
@@ -415,3 +416,18 @@ proc split*(str: string, pattern: Regex): seq[string] =
# but "1 2".split(/ /) needs to return @["1", "2"].
# This handles "2"
result.add(str.substr(lastIdx, str.len - 1))
proc replace*(str: string, pattern: Regex,
subproc: proc (match: RegexMatch): string): string =
# XXX seems very similar to split, maybe I can reduce code duplication
# somehow?
result = ""
var lastIdx = 0
for match in str.findIter(pattern):
let bounds = match.matchBounds
result.add(str.substr(lastIdx, bounds.a - 1))
result.add(subproc(match))
lastIdx = bounds.b
result.add(str.substr(lastIdx, str.len - 1))

View File

@@ -16,3 +16,7 @@ suite "find":
test "overlapping find":
check("222".findAllStr(re"22") == @["22"])
check("2222".findAllStr(re"22") == @["22", "22"])
test "len 0 find":
check("".findAllStr(re"\ ") == newSeq[string]())
check("".findAllStr(re"") == @[""])

8
test/replace.nim Normal file
View File

@@ -0,0 +1,8 @@
include nre
import unittest
suite "replace":
test "replace with 0-length strings":
check("".replace(re"1", proc (v: RegexMatch): string = "1") == "")
check(" ".replace(re"", proc (v: RegexMatch): string = "1") == "1 ")
check("".replace(re"", proc (v: RegexMatch): string = "1") == "1")

View File

@@ -4,3 +4,4 @@ import captures
import find
import split
import match
import replace