File: tcustomstrings.nim

package info (click to toggle)
nim 0.19.4-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 462,356 kB
  • sloc: sh: 11,089; ansic: 4,699; makefile: 706; python: 309; sql: 297; asm: 141; xml: 13
file content (99 lines) | stat: -rw-r--r-- 2,360 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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