diff --git a/lib/std/strbasics.nim b/lib/std/strbasics.nim index beaf9d89a3..63a66cc182 100644 --- a/lib/std/strbasics.nim +++ b/lib/std/strbasics.nim @@ -17,19 +17,30 @@ when defined(nimPreviewSlimSystem): const whitespaces = {' ', '\t', '\v', '\r', '\l', '\f'} +const notJSnotNims = not defined(js) and not defined(nimscript) +template whenNotVmJsNims(normalBody, restrictedBody: untyped) = + ## hack, see: #12517 #12518; Edit together with identical in `system` + when nimvm: + restrictedBody + else: + when notJSnotNims: + normalBody + else: + restrictedBody + proc add*(x: var string, y: openArray[char]) = - ## Concatenates `x` and `y` in place. `y` must not overlap with `x` to - ## allow future `memcpy` optimizations. + ## Concatenates `x` and `y` in place. `y` must not overlap with `x` # Use `{.noalias.}` ? - let n = x.len - x.setLen n + y.len - # pending #19727 - # setLen unnecessarily zeros memory - var i = 0 - while i < y.len: - x[n + i] = y[i] - i.inc - # xxx use `nimCopyMem(x[n].addr, y[0].addr, y.len)` after some refactoring + if y.len == 0: return + let oldLen = x.len + x.setLenUninit(oldLen + y.len) + whenNotVmJsNims(): + {.cast(noSideEffect).}: + copyMem(beginStore(x, oldLen + y.len, oldLen), addr(y[0]), y.len) + endStore(x) + do: + for i, ch in y: + x[oldLen + i] = ch func stripSlice(s: openArray[char], leading = true, trailing = true, chars: set[char] = whitespaces): Slice[int] = ## Returns the slice range of `s` which is stripped `chars`. @@ -74,19 +85,14 @@ func setSlice*(s: var string, slice: Slice[int]) = if first > last: s.setLen(0) return - template impl = - for index in first .. last: - s[index - first] = s[index] if first > 0: - when nimvm: impl() - else: - # not JS and not Nimscript - when not declared(moveMem): - impl() - else: - let p = beginStore(s, s.len) - moveMem(p, addr p[first], last - first + 1) - endStore(s) + whenNotVmJsNims(): + let p = beginStore(s, s.len) + moveMem(p, addr p[first], last - first + 1) + endStore(s) + do: + for index in first .. last: + s[index - first] = s[index] s.setLen(last - first + 1) func strip*(a: var string, leading = true, trailing = true, chars: set[char] = whitespaces) {.inline.} = diff --git a/tests/stdlib/tstrbasics.nim b/tests/stdlib/tstrbasics.nim index bfae55fde9..e812e20ee4 100644 --- a/tests/stdlib/tstrbasics.nim +++ b/tests/stdlib/tstrbasics.nim @@ -90,7 +90,8 @@ proc main() = var a0 = "hi" var b0 = "foobar" when nimvm: - discard # pending bug #15952 + a0.add b0.toOpenArray(1,3) + doAssert a0 == "hioob" else: a0.add b0.toOpenArray(1,3) doAssert a0 == "hioob"