summary refs log tree commit diff stats
path: root/lib/pure/collections/deques.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/collections/deques.nim')
-rw-r--r--lib/pure/collections/deques.nim57
1 files changed, 51 insertions, 6 deletions
diff --git a/lib/pure/collections/deques.nim b/lib/pure/collections/deques.nim
index 328308a9b..409240b37 100644
--- a/lib/pure/collections/deques.nim
+++ b/lib/pure/collections/deques.nim
@@ -38,7 +38,7 @@
 ## Note: For inter thread communication use
 ## a `Channel <channels.html>`_ instead.
 
-import math
+import math, typetraits
 
 type
   Deque*[T] = object
@@ -160,16 +160,18 @@ proc peekLast*[T](deq: Deque[T]): T {.inline.} =
   emptyCheck(deq)
   result = deq.data[(deq.tail - 1) and deq.mask]
 
-template default[T](t: typedesc[T]): T =
-  var v: T
-  v
+template destroy(x: untyped) =
+  when defined(nimNewRuntime) and not supportsCopyMem(type(x)):
+    `=destroy`(x)
+  else:
+    reset(x)
 
 proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} =
   ## Remove and returns the first element of the `deq`.
   emptyCheck(deq)
   dec deq.count
   result = deq.data[deq.head]
-  deq.data[deq.head] = default(type(result))
+  destroy(deq.data[deq.head])
   deq.head = (deq.head + 1) and deq.mask
 
 proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
@@ -178,7 +180,34 @@ proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
   dec deq.count
   deq.tail = (deq.tail - 1) and deq.mask
   result = deq.data[deq.tail]
-  deq.data[deq.tail] = default(type(result))
+  destroy(deq.data[deq.tail])
+
+proc clear*[T](deq: var Deque[T]) {.inline.} =
+  ## Resets the deque so that it is empty.
+  for el in mitems(deq): destroy(el)
+  deq.count = 0
+  deq.tail = deq.head
+
+proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
+  ## Remove `fromFirst` elements from the front of the deque and
+  ## `fromLast` elements from the back. If the supplied number of
+  ## elements exceeds the total number of elements in the deque,
+  ## the deque will remain empty.
+  ##
+  ## Any user defined destructors
+  if fromFirst + fromLast > deq.count:
+    clear(deq)
+    return
+
+  for i in 0 ..< fromFirst:
+    destroy(deq.data[deq.head])
+    deq.head = (deq.head + 1) and deq.mask
+
+  for i in 0 ..< fromLast:
+    destroy(deq.data[deq.tail])
+    deq.tail = (deq.tail - 1) and deq.mask
+
+  dec deq.count, fromFirst + fromLast
 
 proc `$`*[T](deq: Deque[T]): string =
   ## Turn a deque into its string representation.
@@ -215,6 +244,22 @@ when isMainModule:
   assert deq.find(6) >= 0
   assert deq.find(789) < 0
 
+  block:
+    var d = initDeque[int](1)
+    d.addLast 7
+    d.addLast 8
+    d.addLast 10
+    d.addFirst 5
+    d.addFirst 2
+    d.addFirst 1
+    d.addLast 20
+    d.shrink(fromLast = 2)
+    doAssert($d == "[1, 2, 5, 7, 8]")
+    d.shrink(2, 1)
+    doAssert($d == "[5, 7]")
+    d.shrink(2, 2)
+    doAssert d.len == 0
+
   for i in -2 .. 10:
     if i in deq:
       assert deq.contains(i) and deq.find(i) >= 0