summary refs log tree commit diff stats
path: root/tests/destructor/tcustomstrings.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-11-02 10:46:30 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-11-02 10:46:30 +0100
commit1eaeccc15d15d15d2f62ea1648f7dd64722dbd37 (patch)
treeb922cdabc780fa3a8837a6804d2df31793d9e2ca /tests/destructor/tcustomstrings.nim
parente9243a16167b24899d4fcf051f3252b3a5804811 (diff)
parentbd19b5f4d36bb40b4af93d7e15fdfa582e9fe3b7 (diff)
downloadNim-1eaeccc15d15d15d2f62ea1648f7dd64722dbd37.tar.gz
Merge branch 'devel' into araq
Diffstat (limited to 'tests/destructor/tcustomstrings.nim')
-rw-r--r--tests/destructor/tcustomstrings.nim99
1 files changed, 99 insertions, 0 deletions
diff --git a/tests/destructor/tcustomstrings.nim b/tests/destructor/tcustomstrings.nim
new file mode 100644
index 000000000..1a78df20b
--- /dev/null
+++ b/tests/destructor/tcustomstrings.nim
@@ -0,0 +1,99 @@
+discard """
+  output: '''foo bar to appendmore here
+foo bar to appendmore here
+foo bar to appendmore here
+foo bar to appendmore here
+foo bar to appendmore here
+after 20 20'''
+  cmd: '''nim c --newruntime $file'''
+"""
+
+{.this: self.}
+
+type
+  mystring = object
+    len, cap: int
+    data: ptr UncheckedArray[char]
+
+var
+  allocCount, deallocCount: int
+
+proc `=destroy`*(s: var mystring) =
+  if s.data != nil:
+    dealloc(s.data)
+    inc deallocCount
+    s.data = nil
+    s.len = 0
+    s.cap = 0
+
+proc `=sink`*(a: var mystring, b: mystring) =
+  # we hope this is optimized away for not yet alive objects:
+  if a.data != nil and a.data != b.data:
+    dealloc(a.data)
+    inc deallocCount
+  a.len = b.len
+  a.cap = b.cap
+  a.data = b.data
+
+proc `=`*(a: var mystring; b: mystring) =
+  if a.data != nil and a.data != b.data:
+    dealloc(a.data)
+    inc deallocCount
+    a.data = nil
+  a.len = b.len
+  a.cap = b.cap
+  if b.data != nil:
+    a.data = cast[type(a.data)](alloc(a.cap + 1))
+    inc allocCount
+    copyMem(a.data, b.data, a.cap+1)
+
+proc resize(self: var mystring) =
+  if self.cap == 0: self.cap = 8
+  else: self.cap = (self.cap * 3) shr 1
+  if self.data == nil: inc allocCount
+  self.data = cast[type(data)](realloc(self.data, self.cap + 1))
+
+proc add*(self: var mystring; c: char) =
+  if self.len >= self.cap: resize(self)
+  self.data[self.len] = c
+  self.data[self.len+1] = '\0'
+  inc self.len
+
+proc ensure(self: var mystring; newLen: int) =
+  if newLen >= cap:
+    cap = max((cap * 3) shr 1, newLen)
+    if cap > 0:
+      if data == nil: inc allocCount
+      data = cast[type(data)](realloc(data, cap + 1))
+
+proc add*(self: var mystring; y: mystring) =
+  let newLen = len + y.len
+  ensure(self, newLen)
+  copyMem(addr data[len], y.data, y.data.len + 1)
+  len = newLen
+
+proc create*(lit: string): mystring =
+  let newLen = lit.len
+  ensure(result, newLen)
+  copyMem(addr result.data[result.len], unsafeAddr lit[0], newLen + 1)
+  result.len = newLen
+
+proc `&`*(a, b: mystring): mystring =
+  result = a
+  result.add b
+
+proc main(n: int) =
+  var a: mystring
+  let b = create" to append"
+  for i in 0..<n:
+    if i > 4: break
+    a = create"foo bar"
+    let c = b & create"more here"
+    a.add c
+    echo cstring(a.data)
+
+  var x: array[4, mystring]
+  for i in 0..high(x): x[i] = create"added to array"
+
+main(1000)
+echo "after ", allocCount, " ", deallocCount