tcustomstrings.nim 2.3 KB

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