Mercurial > projects > ldc
comparison tango/tango/util/collection/LinkMap.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /* | |
2 File: LinkMap.d | |
3 | |
4 Originally written by Doug Lea and released into the public domain. | |
5 Thanks for the assistance and support of Sun Microsystems Labs, Agorics | |
6 Inc, Loral, and everyone contributing, testing, and using this code. | |
7 | |
8 History: | |
9 Date Who What | |
10 24Sep95 dl@cs.oswego.edu Create from tango.util.collection.d working file | |
11 13Oct95 dl Changed protection statuses | |
12 21Oct95 dl Fixed error in remove | |
13 | |
14 */ | |
15 | |
16 | |
17 module tango.util.collection.LinkMap; | |
18 | |
19 private import tango.core.Exception; | |
20 | |
21 private import tango.io.protocol.model.IReader, | |
22 tango.io.protocol.model.IWriter; | |
23 | |
24 private import tango.util.collection.model.View, | |
25 tango.util.collection.model.GuardIterator; | |
26 | |
27 private import tango.util.collection.impl.LLCell, | |
28 tango.util.collection.impl.LLPair, | |
29 tango.util.collection.impl.MapCollection, | |
30 tango.util.collection.impl.AbstractIterator; | |
31 | |
32 /** | |
33 * Linked lists of (key, element) pairs | |
34 * author: Doug Lea | |
35 **/ | |
36 public class LinkMap(K, T) : MapCollection!(K, T) // , IReadable, IWritable | |
37 { | |
38 alias LLCell!(T) LLCellT; | |
39 alias LLPair!(K, T) LLPairT; | |
40 | |
41 alias MapCollection!(K, T).remove remove; | |
42 alias MapCollection!(K, T) .removeAll removeAll; | |
43 | |
44 // instance variables | |
45 | |
46 /** | |
47 * The head of the list. Null if empty | |
48 **/ | |
49 | |
50 package LLPairT list; | |
51 | |
52 // constructors | |
53 | |
54 /** | |
55 * Make an empty list | |
56 **/ | |
57 | |
58 public this () | |
59 { | |
60 this(null, null, 0); | |
61 } | |
62 | |
63 /** | |
64 * Make an empty list with the supplied element screener | |
65 **/ | |
66 | |
67 public this (Predicate screener) | |
68 { | |
69 this(screener, null, 0); | |
70 } | |
71 | |
72 /** | |
73 * Special version of constructor needed by clone() | |
74 **/ | |
75 protected this (Predicate s, LLPairT l, int c) | |
76 { | |
77 super(s); | |
78 list = l; | |
79 count = c; | |
80 } | |
81 | |
82 /** | |
83 * Make an independent copy of the list. Does not clone elements | |
84 **/ | |
85 | |
86 public LinkMap duplicate() | |
87 { | |
88 if (list is null) | |
89 return new LinkMap (screener, null, 0); | |
90 else | |
91 return new LinkMap (screener, cast(LLPairT)(list.copyList()), count); | |
92 } | |
93 | |
94 | |
95 // Collection methods | |
96 | |
97 /** | |
98 * Implements tango.util.collection.impl.Collection.Collection.contains. | |
99 * Time complexity: O(n). | |
100 * See_Also: tango.util.collection.impl.Collection.Collection.contains | |
101 **/ | |
102 public final bool contains(T element) | |
103 { | |
104 if (!isValidArg(element) || list is null) | |
105 return false; | |
106 | |
107 return list.find(element) !is null; | |
108 } | |
109 | |
110 /** | |
111 * Implements tango.util.collection.impl.Collection.Collection.instances. | |
112 * Time complexity: O(n). | |
113 * See_Also: tango.util.collection.impl.Collection.Collection.instances | |
114 **/ | |
115 public final uint instances(T element) | |
116 { | |
117 if (!isValidArg(element) || list is null) | |
118 return 0; | |
119 | |
120 return list.count(element); | |
121 } | |
122 | |
123 /** | |
124 * Implements tango.util.collection.impl.Collection.Collection.elements. | |
125 * Time complexity: O(1). | |
126 * See_Also: tango.util.collection.impl.Collection.Collection.elements | |
127 **/ | |
128 public final GuardIterator!(T) elements() | |
129 { | |
130 return keys(); | |
131 } | |
132 | |
133 /*********************************************************************** | |
134 | |
135 Implements tango.util.collection.model.View.View.opApply | |
136 Time complexity: O(n) | |
137 | |
138 See_Also: tango.util.collection.model.View.View.opApply | |
139 | |
140 ************************************************************************/ | |
141 | |
142 int opApply (int delegate (inout T value) dg) | |
143 { | |
144 auto scope iterator = new MapIterator!(K, T)(this); | |
145 return iterator.opApply (dg); | |
146 } | |
147 | |
148 | |
149 /*********************************************************************** | |
150 | |
151 Implements tango.util.collection.MapView.opApply | |
152 Time complexity: O(n) | |
153 | |
154 See_Also: tango.util.collection.MapView.opApply | |
155 | |
156 ************************************************************************/ | |
157 | |
158 int opApply (int delegate (inout K key, inout T value) dg) | |
159 { | |
160 auto scope iterator = new MapIterator!(K, T)(this); | |
161 return iterator.opApply (dg); | |
162 } | |
163 | |
164 | |
165 // Map methods | |
166 | |
167 | |
168 /** | |
169 * Implements tango.util.collection.Map.containsKey. | |
170 * Time complexity: O(n). | |
171 * See_Also: tango.util.collection.Map.containsKey | |
172 **/ | |
173 public final bool containsKey(K key) | |
174 { | |
175 if (!isValidKey(key) || list is null) | |
176 return false; | |
177 | |
178 return list.findKey(key) !is null; | |
179 } | |
180 | |
181 /** | |
182 * Implements tango.util.collection.Map.containsPair | |
183 * Time complexity: O(n). | |
184 * See_Also: tango.util.collection.Map.containsPair | |
185 **/ | |
186 public final bool containsPair(K key, T element) | |
187 { | |
188 if (!isValidKey(key) || !isValidArg(element) || list is null) | |
189 return false; | |
190 return list.find(key, element) !is null; | |
191 } | |
192 | |
193 /** | |
194 * Implements tango.util.collection.Map.keys. | |
195 * Time complexity: O(1). | |
196 * See_Also: tango.util.collection.Map.keys | |
197 **/ | |
198 public final PairIterator!(K, T) keys() | |
199 { | |
200 return new MapIterator!(K, T)(this); | |
201 } | |
202 | |
203 /** | |
204 * Implements tango.util.collection.Map.get. | |
205 * Time complexity: O(n). | |
206 * See_Also: tango.util.collection.Map.get | |
207 **/ | |
208 public final T get(K key) | |
209 { | |
210 checkKey(key); | |
211 if (list !is null) | |
212 { | |
213 auto p = list.findKey(key); | |
214 if (p !is null) | |
215 return p.element(); | |
216 } | |
217 throw new NoSuchElementException("no matching Key"); | |
218 } | |
219 | |
220 /** | |
221 * Return the element associated with Key key. | |
222 * Params: | |
223 * key = a key | |
224 * Returns: whether the key is contained or not | |
225 **/ | |
226 | |
227 public final bool get(K key, inout T element) | |
228 { | |
229 checkKey(key); | |
230 if (list !is null) | |
231 { | |
232 auto p = list.findKey(key); | |
233 if (p !is null) | |
234 { | |
235 element = p.element(); | |
236 return true; | |
237 } | |
238 } | |
239 return false; | |
240 } | |
241 | |
242 | |
243 | |
244 /** | |
245 * Implements tango.util.collection.Map.keyOf. | |
246 * Time complexity: O(n). | |
247 * See_Also: tango.util.collection.Map.keyOf | |
248 **/ | |
249 public final bool keyOf(inout K key, T value) | |
250 { | |
251 if (!isValidArg(value) || count is 0) | |
252 return false; | |
253 | |
254 auto p = (cast(LLPairT)(list.find(value))); | |
255 if (p is null) | |
256 return false; | |
257 | |
258 key = p.key(); | |
259 return true; | |
260 } | |
261 | |
262 | |
263 // MutableCollection methods | |
264 | |
265 /** | |
266 * Implements tango.util.collection.impl.Collection.Collection.clear. | |
267 * Time complexity: O(1). | |
268 * See_Also: tango.util.collection.impl.Collection.Collection.clear | |
269 **/ | |
270 public final void clear() | |
271 { | |
272 list = null; | |
273 setCount(0); | |
274 } | |
275 | |
276 /** | |
277 * Implements tango.util.collection.impl.Collection.Collection.replaceOneOf | |
278 * Time complexity: O(n). | |
279 * See_Also: tango.util.collection.impl.Collection.Collection.replaceOneOf | |
280 **/ | |
281 public final void replace (T oldElement, T newElement) | |
282 { | |
283 replace_(oldElement, newElement, false); | |
284 } | |
285 | |
286 /** | |
287 * Implements tango.util.collection.impl.Collection.Collection.replaceAllOf. | |
288 * Time complexity: O(n). | |
289 * See_Also: tango.util.collection.impl.Collection.Collection.replaceAllOf | |
290 **/ | |
291 public final void replaceAll(T oldElement, T newElement) | |
292 { | |
293 replace_(oldElement, newElement, true); | |
294 } | |
295 | |
296 /** | |
297 * Implements tango.util.collection.impl.Collection.Collection.removeAll. | |
298 * Time complexity: O(n). | |
299 * See_Also: tango.util.collection.impl.Collection.Collection.removeAll | |
300 **/ | |
301 public final void removeAll(T element) | |
302 { | |
303 remove_(element, true); | |
304 } | |
305 | |
306 /** | |
307 * Implements tango.util.collection.impl.Collection.Collection.removeOneOf. | |
308 * Time complexity: O(n). | |
309 * See_Also: tango.util.collection.impl.Collection.Collection.removeOneOf | |
310 **/ | |
311 public final void remove(T element) | |
312 { | |
313 remove_(element, false); | |
314 } | |
315 | |
316 /** | |
317 * Implements tango.util.collection.impl.Collection.Collection.take. | |
318 * Time complexity: O(1). | |
319 * takes the first element on the list | |
320 * See_Also: tango.util.collection.impl.Collection.Collection.take | |
321 **/ | |
322 public final T take() | |
323 { | |
324 if (list !is null) | |
325 { | |
326 auto v = list.element(); | |
327 list = cast(LLPairT)(list.next()); | |
328 decCount(); | |
329 return v; | |
330 } | |
331 checkIndex(0); | |
332 return T.init; // not reached | |
333 } | |
334 | |
335 | |
336 // MutableMap methods | |
337 | |
338 /** | |
339 * Implements tango.util.collection.impl.MapCollection.MapCollection.add. | |
340 * Time complexity: O(n). | |
341 * See_Also: tango.util.collection.impl.MapCollection.MapCollection.add | |
342 **/ | |
343 public final void add (K key, T element) | |
344 { | |
345 checkKey(key); | |
346 checkElement(element); | |
347 | |
348 if (list !is null) | |
349 { | |
350 auto p = list.findKey(key); | |
351 if (p !is null) | |
352 { | |
353 if (p.element() != (element)) | |
354 { | |
355 p.element(element); | |
356 incVersion(); | |
357 } | |
358 return ; | |
359 } | |
360 } | |
361 list = new LLPairT(key, element, list); | |
362 incCount(); | |
363 } | |
364 | |
365 | |
366 /** | |
367 * Implements tango.util.collection.impl.MapCollection.MapCollection.remove. | |
368 * Time complexity: O(n). | |
369 * See_Also: tango.util.collection.impl.MapCollection.MapCollection.remove | |
370 **/ | |
371 public final void removeKey (K key) | |
372 { | |
373 if (!isValidKey(key) || list is null) | |
374 return ; | |
375 | |
376 auto p = list; | |
377 auto trail = p; | |
378 | |
379 while (p !is null) | |
380 { | |
381 auto n = cast(LLPairT)(p.next()); | |
382 if (p.key() == (key)) | |
383 { | |
384 decCount(); | |
385 if (p is list) | |
386 list = n; | |
387 else | |
388 trail.unlinkNext(); | |
389 return ; | |
390 } | |
391 else | |
392 { | |
393 trail = p; | |
394 p = n; | |
395 } | |
396 } | |
397 } | |
398 | |
399 /** | |
400 * Implements tango.util.collection.impl.MapCollection.MapCollection.replaceElement. | |
401 * Time complexity: O(n). | |
402 * See_Also: tango.util.collection.impl.MapCollection.MapCollection.replaceElement | |
403 **/ | |
404 public final void replacePair (K key, T oldElement, T newElement) | |
405 { | |
406 if (!isValidKey(key) || !isValidArg(oldElement) || list is null) | |
407 return ; | |
408 | |
409 auto p = list.find(key, oldElement); | |
410 if (p !is null) | |
411 { | |
412 checkElement(newElement); | |
413 p.element(newElement); | |
414 incVersion(); | |
415 } | |
416 } | |
417 | |
418 private final void remove_(T element, bool allOccurrences) | |
419 { | |
420 if (!isValidArg(element) || count is 0) | |
421 return ; | |
422 | |
423 auto p = list; | |
424 auto trail = p; | |
425 | |
426 while (p !is null) | |
427 { | |
428 auto n = cast(LLPairT)(p.next()); | |
429 if (p.element() == (element)) | |
430 { | |
431 decCount(); | |
432 if (p is list) | |
433 { | |
434 list = n; | |
435 trail = n; | |
436 } | |
437 else | |
438 trail.next(n); | |
439 | |
440 if (!allOccurrences || count is 0) | |
441 return ; | |
442 else | |
443 p = n; | |
444 } | |
445 else | |
446 { | |
447 trail = p; | |
448 p = n; | |
449 } | |
450 } | |
451 } | |
452 | |
453 /** | |
454 * Helper for replace | |
455 **/ | |
456 | |
457 private final void replace_(T oldElement, T newElement, bool allOccurrences) | |
458 { | |
459 if (list is null || !isValidArg(oldElement) || oldElement == (newElement)) | |
460 return ; | |
461 | |
462 auto p = list.find(oldElement); | |
463 while (p !is null) | |
464 { | |
465 checkElement(newElement); | |
466 p.element(newElement); | |
467 incVersion(); | |
468 if (!allOccurrences) | |
469 return ; | |
470 p = p.find(oldElement); | |
471 } | |
472 } | |
473 | |
474 // ImplementationCheckable methods | |
475 | |
476 /** | |
477 * Implements tango.util.collection.model.View.View.checkImplementation. | |
478 * See_Also: tango.util.collection.model.View.View.checkImplementation | |
479 **/ | |
480 public override void checkImplementation() | |
481 { | |
482 super.checkImplementation(); | |
483 | |
484 assert(((count is 0) is (list is null))); | |
485 assert((list is null || list._length() is count)); | |
486 | |
487 for (auto p = list; p !is null; p = cast(LLPairT)(p.next())) | |
488 { | |
489 assert(allows(p.element())); | |
490 assert(allowsKey(p.key())); | |
491 assert(containsKey(p.key())); | |
492 assert(contains(p.element())); | |
493 assert(instances(p.element()) >= 1); | |
494 assert(containsPair(p.key(), p.element())); | |
495 } | |
496 } | |
497 | |
498 | |
499 /*********************************************************************** | |
500 | |
501 opApply() has migrated here to mitigate the virtual call | |
502 on method get() | |
503 | |
504 ************************************************************************/ | |
505 | |
506 private static class MapIterator(K, V) : AbstractMapIterator!(K, V) | |
507 { | |
508 private LLPairT pair; | |
509 | |
510 public this (LinkMap map) | |
511 { | |
512 super (map); | |
513 pair = map.list; | |
514 } | |
515 | |
516 public final V get(inout K key) | |
517 { | |
518 if (pair) | |
519 key = pair.key; | |
520 return get(); | |
521 } | |
522 | |
523 public final V get() | |
524 { | |
525 decRemaining(); | |
526 auto v = pair.element(); | |
527 pair = cast(LLPairT) pair.next(); | |
528 return v; | |
529 } | |
530 | |
531 int opApply (int delegate (inout V value) dg) | |
532 { | |
533 int result; | |
534 | |
535 for (auto i=remaining(); i--;) | |
536 { | |
537 auto value = get(); | |
538 if ((result = dg(value)) != 0) | |
539 break; | |
540 } | |
541 return result; | |
542 } | |
543 | |
544 int opApply (int delegate (inout K key, inout V value) dg) | |
545 { | |
546 K key; | |
547 int result; | |
548 | |
549 for (auto i=remaining(); i--;) | |
550 { | |
551 auto value = get(key); | |
552 if ((result = dg(key, value)) != 0) | |
553 break; | |
554 } | |
555 return result; | |
556 } | |
557 } | |
558 } | |
559 | |
560 | |
561 | |
562 debug(Test) | |
563 { | |
564 void main() | |
565 { | |
566 auto map = new LinkMap!(Object, double); | |
567 | |
568 foreach (key, value; map.keys) {typeof(key) x; x = key;} | |
569 | |
570 foreach (value; map.keys) {} | |
571 | |
572 foreach (value; map.elements) {} | |
573 | |
574 auto keys = map.keys(); | |
575 while (keys.more) | |
576 auto v = keys.get(); | |
577 | |
578 foreach (value; map) {} | |
579 foreach (key, value; map) {} | |
580 | |
581 map.checkImplementation(); | |
582 } | |
583 } |