1 2 module ws.list; 3 4 import std.conv, ws.io; 5 6 __gshared: 7 8 9 class List(T) { 10 11 protected { 12 13 struct Node { 14 T obj; 15 Node* prev; 16 Node* next; 17 } 18 19 Node* mBegin; 20 Node* mEnd; 21 size_t mLength; 22 23 alias Type = T; 24 25 } 26 27 28 TList opCast(TList)(){ 29 auto list = new TList; 30 foreach(e; this) 31 list ~= cast(TList.Type)e; 32 return list; 33 } 34 35 36 Node* checkBegin(){ 37 if(!mBegin){ 38 mBegin = new Node; 39 mEnd = mBegin; 40 } 41 return mBegin; 42 } 43 44 Node* checkEnd(){ 45 checkBegin(); 46 return mEnd; 47 } 48 49 ref T opIndex(size_t idx){ 50 assert(idx < mLength); 51 Node* it = mBegin; 52 while(idx--) 53 it = it.next; 54 return it.obj; 55 } 56 57 void opOpAssign(string op)(T e){ 58 static if(op=="~") 59 push(e); 60 else static if(op=="-") 61 remove(e); 62 else static assert(0, "Operator " ~ op ~ " not implemented"); 63 } 64 65 void push(T e){ 66 if(!mBegin){ 67 mBegin = new Node; 68 mBegin.obj = e; 69 mEnd = mBegin; 70 }else{ 71 mEnd.next = new Node; 72 mEnd.next.prev = mEnd; 73 mEnd.next.obj = e; 74 mEnd = mEnd.next; 75 } 76 ++mLength; 77 } 78 79 void pushFront(T e){ 80 if(!mBegin){ 81 mBegin = new Node; 82 mBegin.obj = e; 83 mEnd = mBegin; 84 }else{ 85 mBegin.prev = new Node; 86 mBegin.prev.next = mBegin; 87 mBegin.prev.obj = e; 88 mBegin = mBegin.prev; 89 } 90 ++mLength; 91 } 92 93 94 Iterator insert(Iterator where, T obj, bool before = false){ 95 auto node = new Node; 96 node.next = (before ? where.node : where.node.next); 97 node.prev = (before ? where.node.prev : where.node); 98 node.obj = obj; 99 if(node.next) 100 node.next.prev = node; 101 if(node.prev) 102 node.prev.next = node; 103 ++mLength; 104 return Iterator(node); 105 } 106 107 108 ref T popBack(){ 109 assert(mLength, "list is empty"); 110 auto tmp = mEnd; 111 if(mEnd.prev){ 112 mEnd.prev.next = null; 113 mEnd = tmp.prev; 114 --mLength; 115 }else 116 clear(); 117 return tmp.obj; 118 } 119 120 ref T popFront(){ 121 assert(mLength, "list is empty"); 122 auto tmp = mBegin; 123 if(mBegin.next){ 124 mBegin.next.prev = null; 125 mBegin = mBegin.next; 126 --mLength; 127 }else 128 clear(); 129 return tmp.obj; 130 } 131 132 void remove(T e){ 133 auto it = mBegin; 134 while(it){ 135 if(it.obj == e) break; 136 it = it.next; 137 } 138 if(!it) 139 throw new Exception("element not in list"); 140 remove(Iterator(it)); 141 } 142 143 144 void remove(Iterator it){ 145 if(it.node.prev) 146 it.node.prev.next = it.node.next; 147 else 148 mBegin = it.node.next; 149 if(it.node.next) 150 it.node.next.prev = it.node.prev; 151 else 152 mEnd = it.node.prev; 153 --mLength; 154 } 155 156 157 List opBinary(string op)(List other) if(op=="~"){ 158 auto n = new List; 159 foreach(c; this) 160 n.push(c); 161 foreach(c; other) 162 n.push(c); 163 return n; 164 } 165 166 167 int opApply(int delegate(Iterator,T) callback){ 168 int result = 0; 169 auto it = begin(); 170 while(it){ 171 result = callback(it, it.get()); 172 it = it.next; 173 if(result) 174 break; 175 } 176 return result; 177 } 178 179 int opApply(int delegate(T) cb){ 180 return opApply((i, T e){ 181 return cb(e); 182 }); 183 } 184 185 186 int opApplyReverse(int delegate(T) callback){ 187 int result = 0; 188 auto it = mEnd; 189 while(it){ 190 auto obj = it.obj; 191 it = it.prev; 192 result = callback(obj); 193 if(result) break; 194 } 195 return result; 196 } 197 198 199 override string toString(){ 200 string tmp = "List!" ~ typeid(T).toString() ~ " = [\n"; 201 auto it = mBegin; 202 while(it){ 203 tmp ~= "\t" ~ to!string(it.obj) ~ ",\n"; 204 it = it.next; 205 } 206 tmp ~= "]"; 207 return tmp; 208 } 209 210 211 @property bool empty() const { 212 return !mBegin; 213 } 214 215 216 void clear(){ 217 mBegin = null; 218 mEnd = null; 219 mLength = 0; 220 } 221 222 223 @property ref T front(){ 224 assert(mBegin); 225 return mBegin.obj; 226 } 227 228 @property void front(ref T f){ 229 assert(mBegin); 230 mBegin.obj = f; 231 } 232 233 234 @property ref T back(){ 235 assert(mEnd); 236 return mEnd.obj; 237 } 238 239 @property void back(ref T b){ 240 assert(mEnd); 241 mEnd.obj = b; 242 } 243 244 @property nothrow size_t length(){ 245 return mLength; 246 } 247 248 249 @property nothrow Iterator begin(){ 250 return Iterator(mBegin); 251 } 252 253 254 @property nothrow Iterator end(){ 255 return Iterator(mEnd); 256 } 257 258 259 struct Iterator { 260 261 Node* node; 262 263 T get(){ 264 return node.obj; 265 } 266 267 @property Iterator prev(){ 268 return Iterator(node.prev); 269 } 270 271 @property Iterator next(){ 272 return Iterator(node.next); 273 } 274 275 private nothrow this(Node* node){ 276 this.node = node; 277 } 278 279 bool opCast(T)() if(is(T==bool)) { 280 return node !is null; 281 } 282 283 Iterator opUnary(string s)(){ 284 static if(s == "++"){ 285 if(node.next) 286 node = node.next; 287 }else static if(s == "--"){ 288 if(node.prev) 289 node = node.prev; 290 }else 291 assert(false, "Not implemented"); 292 return this; 293 } 294 295 } 296 297 298 unittest { 299 auto test = new List!int; 300 test.push(5); 301 test.push(10); 302 assert(test.mLength == 2); 303 304 assert(test[0]*test[1] == 5*10); 305 306 test.remove(5); 307 assert(test.mLength == 1); 308 309 assert(test[0] == 10); 310 311 test.push(12); 312 auto it = test.end(); 313 test.insert(it, 11, true); 314 315 assert(test.mLength == 3); 316 317 foreach(i; test) 318 if(i == 11){ 319 test.remove(i); 320 test.push(100); 321 } 322 323 assert(test[0] == 10); 324 assert(test[1] == 12); 325 assert(test[2] == 100); 326 assert(test.mLength == 3); 327 328 test.back *= 5; 329 assert(test.back == 500); 330 331 foreach(i; test) 332 test.popFront(); 333 assert(test.mLength == 0); 334 335 } 336 337 } 338 339