diff options
Diffstat (limited to 'tests/destructor/tcustomstrings.nim')
-rw-r--r-- | tests/destructor/tcustomstrings.nim | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/tests/destructor/tcustomstrings.nim b/tests/destructor/tcustomstrings.nim new file mode 100644 index 000000000..31891856b --- /dev/null +++ b/tests/destructor/tcustomstrings.nim @@ -0,0 +1,97 @@ +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''' +joinable: false +""" + +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(self.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 >= self.cap: + self.cap = max((self.cap * 3) shr 1, newLen) + if self.cap > 0: + if self.data == nil: inc allocCount + self.data = cast[type(self.data)](realloc(self.data, self.cap + 1)) + +proc add*(self: var mystring; y: mystring) = + let newLen = self.len + y.len + ensure(self, newLen) + copyMem(addr self.data[self.len], y.data, y.data.len + 1) + self.len = newLen + +proc create*(lit: string): mystring = + let newLen = lit.len + ensure(result, newLen) + copyMem(addr result.data[result.len], addr 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 |