diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-09-15 09:27:51 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-09-15 09:27:51 +0200 |
commit | 39f0195ebf30cc9f4b96953423298d7a2130eac8 (patch) | |
tree | bb4daf580c239b59d232e186814b69fc642ce6d5 /lib/pure/strutils.nim | |
parent | bc738d63a728ee6030cc224c8808990a6f641feb (diff) | |
parent | 2ef65d5cdf3d65cbfab4c39796ddb4e70e9ebb37 (diff) | |
download | Nim-39f0195ebf30cc9f4b96953423298d7a2130eac8.tar.gz |
Merge branch 'devel' into araq
Diffstat (limited to 'lib/pure/strutils.nim')
-rw-r--r-- | lib/pure/strutils.nim | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 346248a25..2f2b89955 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1551,6 +1551,37 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, # copy the rest: add result, substr(s, i) +proc multiReplace*(s: string, replacements: varargs[(string, string)]): string {.noSideEffect.} = + ## Same as replace, but specialized for doing multiple replacements in a single + ## pass through the input string. + ## + ## Calling replace multiple times after each other is inefficient and result in too many allocations + ## follwed by immediate deallocations as portions of the string gets replaced. + ## multiReplace performs all replacements in a single pass. + ## + ## If the resulting string is not longer than the original input string, only a single + ## memory allocation is required. + ## + ## The order of the replacements does matter. Earlier replacements are preferred over later + ## replacements in the argument list. + result = newStringOfCap(s.len) + var i = 0 + var fastChk: set[char] = {} + for tup in replacements: fastChk.incl(tup[0][0]) # Include first character of all replacements + while i < s.len: + block sIteration: + # Assume most chars in s are not candidates for any replacement operation + if s[i] in fastChk: + for tup in replacements: + if s.continuesWith(tup[0], i): + add result, tup[1] + inc(i, tup[0].len) + break sIteration + # No matching replacement found + # copy current character from s + add result, s[i] + inc(i) + proc delete*(s: var string, first, last: int) {.noSideEffect, rtl, extern: "nsuDelete".} = ## Deletes in `s` the characters at position `first` .. `last`. @@ -2324,6 +2355,10 @@ when isMainModule: doAssert " foo\n bar".indent(4, "Q") == "QQQQ foo\nQQQQ bar" + doAssert "abba".multiReplace(("a", "b"), ("b", "a")) == "baab" + doAssert "Hello World.".multiReplace(("ello", "ELLO"), ("World.", "PEOPLE!")) == "HELLO PEOPLE!" + doAssert "aaaa".multiReplace(("a", "aa"), ("aa", "bb")) == "aaaaaaaa" + doAssert isAlphaAscii('r') doAssert isAlphaAscii('A') doAssert(not isAlphaAscii('$')) |