1 /** 2 * Linked list containers 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.utils.container.list; 15 16 public import ae.utils.container.listnode; 17 18 import ae.utils.alloc; 19 20 /// Organizes a bunch of objects in a linked list. 21 /// Not very efficient for reference types, since it results in two allocations per object. 22 struct ListParts(T, bool HASPREV, bool HASTAIL, alias ALLOCATOR=heapAllocator) 23 { 24 alias ListNode!(T, HASPREV) Node; 25 enum ITEM_EXPR = q{.value}; 26 27 struct Data 28 { 29 mixin ListCommon.Data!(Node*, HASPREV, HASTAIL); 30 } 31 32 static template Impl(alias data) 33 { 34 mixin ListCommon.Impl!(Node*, HASPREV, HASTAIL, data) common; 35 36 Node* pushFront(T v) 37 { 38 auto node = ALLOCATOR.allocate!Node(); 39 node.value = v; 40 common.pushFront(node); 41 return node; 42 } 43 44 static if (HASTAIL) 45 Node* pushBack(T v) 46 { 47 auto node = ALLOCATOR.allocate!Node(); 48 node.value = v; 49 common.pushBack(node); 50 return node; 51 } 52 53 static if (HASTAIL) 54 deprecated alias pushBack add; 55 56 static if (HASPREV) 57 void remove(Node* node) 58 { 59 common.remove(node); 60 static if (is(typeof(&ALLOCATOR.free))) 61 ALLOCATOR.free(node); 62 } 63 } 64 } 65 66 alias PartsWrapper!ListParts List; 67 68 /// Singly-ended singly-linked list. Usable as a stack. 69 template SList(T) 70 { 71 alias List!(T, false, false) SList; 72 } 73 74 /// Double-ended singly-linked list. Usable as a stack or queue. 75 template DESList(T) 76 { 77 alias List!(T, false, true) DESList; 78 } 79 80 /// Doubly-linked list. Usable as a stack, queue or deque. 81 template DList(T) 82 { 83 alias List!(T, true, true) DList; 84 } 85 86 /// Doubly-linked but single-ended list. 87 /// Can't be used as a queue or deque, but supports arbitrary removal. 88 template SEDList(T) 89 { 90 alias List!(T, true, false) SEDList; 91 } 92 93 unittest 94 { 95 DList!int l; 96 auto i1 = l.pushBack(1); 97 auto i2 = l.pushBack(2); 98 auto i3 = l.pushBack(3); 99 l.remove(i2); 100 101 int[] a; 102 foreach (i; l) 103 a ~= i; 104 assert(a == [1, 3]); 105 106 import std.algorithm; 107 assert(equal(l.iterator, [1, 3])); 108 } 109