tcustomstrings.nim 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. discard """
  2. output: '''foo bar to appendmore here
  3. foo bar to appendmore here
  4. foo bar to appendmore here
  5. foo bar to appendmore here
  6. foo bar to appendmore here
  7. after 20 20'''
  8. joinable: false
  9. """
  10. type
  11. mystring = object
  12. len, cap: int
  13. data: ptr UncheckedArray[char]
  14. var
  15. allocCount, deallocCount: int
  16. proc `=destroy`*(s: var mystring) =
  17. if s.data != nil:
  18. dealloc(s.data)
  19. inc deallocCount
  20. s.data = nil
  21. s.len = 0
  22. s.cap = 0
  23. proc `=sink`*(a: var mystring, b: mystring) =
  24. # we hope this is optimized away for not yet alive objects:
  25. if a.data != nil and a.data != b.data:
  26. dealloc(a.data)
  27. inc deallocCount
  28. a.len = b.len
  29. a.cap = b.cap
  30. a.data = b.data
  31. proc `=`*(a: var mystring; b: mystring) =
  32. if a.data != nil and a.data != b.data:
  33. dealloc(a.data)
  34. inc deallocCount
  35. a.data = nil
  36. a.len = b.len
  37. a.cap = b.cap
  38. if b.data != nil:
  39. a.data = cast[type(a.data)](alloc(a.cap + 1))
  40. inc allocCount
  41. copyMem(a.data, b.data, a.cap+1)
  42. proc resize(self: var mystring) =
  43. if self.cap == 0: self.cap = 8
  44. else: self.cap = (self.cap * 3) shr 1
  45. if self.data == nil: inc allocCount
  46. self.data = cast[type(self.data)](realloc(self.data, self.cap + 1))
  47. proc add*(self: var mystring; c: char) =
  48. if self.len >= self.cap: resize(self)
  49. self.data[self.len] = c
  50. self.data[self.len+1] = '\0'
  51. inc self.len
  52. proc ensure(self: var mystring; newLen: int) =
  53. if newLen >= self.cap:
  54. self.cap = max((self.cap * 3) shr 1, newLen)
  55. if self.cap > 0:
  56. if self.data == nil: inc allocCount
  57. self.data = cast[type(self.data)](realloc(self.data, self.cap + 1))
  58. proc add*(self: var mystring; y: mystring) =
  59. let newLen = self.len + y.len
  60. ensure(self, newLen)
  61. copyMem(addr self.data[self.len], y.data, y.data.len + 1)
  62. self.len = newLen
  63. proc create*(lit: string): mystring =
  64. let newLen = lit.len
  65. ensure(result, newLen)
  66. copyMem(addr result.data[result.len], addr lit[0], newLen + 1)
  67. result.len = newLen
  68. proc `&`*(a, b: mystring): mystring =
  69. result = a
  70. result.add b
  71. proc main(n: int) =
  72. var a: mystring
  73. let b = create" to append"
  74. for i in 0..<n:
  75. if i > 4: break
  76. a = create"foo bar"
  77. let c = b & create"more here"
  78. a.add c
  79. echo cstring(a.data)
  80. var x: array[4, mystring]
  81. for i in 0..high(x): x[i] = create"added to array"
  82. main(1000)
  83. echo "after ", allocCount, " ", deallocCount