diff options
author | Araq <rumpf_a@web.de> | 2014-08-06 09:54:23 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-08-06 09:54:23 +0200 |
commit | a64d733029b1f8c76575f5d117399d587346b9cc (patch) | |
tree | b0da407036a22032376169fc1977e42f934b8b4d /lib | |
parent | 1e8a9aead060d27099bdd8634cbab6b89ecd9995 (diff) | |
download | Nim-a64d733029b1f8c76575f5d117399d587346b9cc.tar.gz |
some bugfixes for 'deepCopy'
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/deepcopy.nim | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index d3f9c5d7c..5c10ef9ed 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -32,6 +32,12 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} = genericDeepCopyAux(dest, src, m) of nkNone: sysAssert(false, "genericDeepCopyAux") +proc copyDeepString(src: NimString): NimString {.inline.} = + if src != nil: + result = rawNewString(src.space) + result.len = src.len + c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char)) + proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = var d = cast[TAddress](dest) @@ -44,10 +50,10 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = if s2 == nil: unsureAsgnRef(x, s2) else: - unsureAsgnRef(x, copyString(cast[NimString](s2))) + unsureAsgnRef(x, copyDeepString(cast[NimString](s2))) of tySequence: var s2 = cast[PPointer](src)[] - var seq = cast[PGenericSeq](s2) + var seq = cast[PGenericSeq](s2) var x = cast[PPointer](dest) if s2 == nil: unsureAsgnRef(x, s2) @@ -76,25 +82,31 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size), cast[pointer](s +% i*% mt.base.size), mt.base) of tyRef: - var z: pointer if mt.base.deepCopy != nil: - z = mt.base.deepCopy(cast[PPointer](s)[]) + let z = mt.base.deepCopy(cast[PPointer](src)[]) + unsureAsgnRef(cast[PPointer](dest), z) else: # we modify the header of the cell temporarily; instead of the type # field we store a forwarding pointer. XXX This is bad when the cloning # fails due to OOM etc. - let x = usrToCell(cast[PPointer](s)[]) + let s2 = cast[PPointer](src)[] + if s2 == nil: + unsureAsgnRef(cast[PPointer](dest), s2) + return + let x = usrToCell(s2) let forw = cast[int](x.typ) if (forw and 1) == 1: # we stored a forwarding pointer, so let's use that: - z = cast[pointer](forw and not 1) + let z = cast[pointer](forw and not 1) + unsureAsgnRef(cast[PPointer](dest), z) else: let realType = x.typ - z = newObj(realType, realType.base.size) + let z = newObj(realType, realType.base.size) + + unsureAsgnRef(cast[PPointer](dest), z) x.typ = cast[PNimType](cast[int](z) or 1) - genericDeepCopyAux(dest, addr(z), realType) + genericDeepCopyAux(z, s2, realType.base) x.typ = realType - unsureAsgnRef(cast[PPointer](dest), z) of tyPtr: # no cycle check here, but also not really required if mt.base.deepCopy != nil: @@ -102,12 +114,13 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = else: cast[PPointer](dest)[] = cast[PPointer](s)[] else: - copyMem(dest, src, mt.size) # copy raw bits + copyMem(dest, src, mt.size) proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = genericDeepCopyAux(dest, src, mt) proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = + # also invoked for 'string' var src = src genericDeepCopy(dest, addr(src), mt) |