summary refs log tree commit diff stats
path: root/lib/core
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-04-06 00:57:09 +0200
committerAraq <rumpf_a@web.de>2019-04-06 17:32:53 +0200
commitfab75fbaf1a2dd94cedfc0b41173edf49b581c6e (patch)
tree51cd6390cecc7ef8e6e7866a62238912eb2c2c99 /lib/core
parent1a202b9754cc347a4f02504944a4edb8dbb5bdc0 (diff)
downloadNim-fab75fbaf1a2dd94cedfc0b41173edf49b581c6e.tar.gz
added nimAsgnStrV2 compilerproc
Diffstat (limited to 'lib/core')
-rw-r--r--lib/core/strs.nim35
1 files changed, 28 insertions, 7 deletions
diff --git a/lib/core/strs.nim b/lib/core/strs.nim
index 5c291e411..7dd65bdb3 100644
--- a/lib/core/strs.nim
+++ b/lib/core/strs.nim
@@ -41,12 +41,11 @@ template isLiteral(s): bool = s.p == nil or s.p.allocator == nil
 
 template contentSize(cap): int = cap + 1 + sizeof(int) + sizeof(Allocator)
 
-when not defined(nimV2):
-
-  template frees(s) =
-    if not isLiteral(s):
-      s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap))
+template frees(s) =
+  if not isLiteral(s):
+    s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap))
 
+when not defined(nimV2):
   proc `=destroy`(s: var string) =
     var a = cast[ptr NimStringV2](addr s)
     frees(a)
@@ -164,9 +163,31 @@ proc mnewString(len: int): NimStringV2 {.compilerProc.} =
     result = NimStringV2(len: len, p: p)
 
 proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} =
-  if newLen > s.len:
+  if newLen > s.len or isLiteral(s):
     prepareAdd(s, newLen - s.len)
-  # XXX This is wrong for const strings that got moved into 's'!
   s.len = newLen
   # this also only works because the destructor
   # looks at s.p and not s.len
+
+proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
+  # self assignment is fine!
+  #if unlikely(a.p == b.p): return
+  if isLiteral(b):
+    # we can shallow copy literals:
+    frees(a)
+    a.len = b.len
+    a.p = b.p
+  elif isLiteral(a) or a.p.cap < b.len:
+    let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
+    # we have to allocate the 'cap' here, consider
+    # 'let y = newStringOfCap(); var x = y'
+    # on the other hand... These get turned into moves now.
+    a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
+    a.p.allocator = allocator
+    a.p.cap = b.len
+    a.len = b.len
+    copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
+  else:
+    a.len = b.len
+    # reuse the storage we already have:
+    copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)