1 /**
2 * This module implements an associative array.
3 * @nogc associative array, replacement for std::map and std::set.
4 * Implementation of Red Black Tree from Phobos.
5 *
6 * Copyright: Copyright Auburn Sounds 2015-2016
7 * Copyright: Copyright (C) 2008- by Steven Schveighoffer. Other code
8 * Copyright: 2010- Andrei Alexandrescu. All rights reserved by the respective holders.
9 * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
10 * Authors:   Authors: Steven Schveighoffer, $(HTTP erdani.com, Andrei Alexandrescu), Guillaume Piolat
11 */
12 module dplug.core.map;
13 
14 import std.functional: binaryFun;
15 
16 import dplug.core.nogc;
17 
18 nothrow:
19 @nogc:
20 
21 /// Creates a new empty `Map`.
22 Map!(K, V, less, allowDuplicates) makeMap(K, V, alias less = "a < b", bool allowDuplicates = false)()
23 {
24     return Map!(K, V, less, allowDuplicates)(42);
25 }
26 
27 /// Tree-map, designed to replace std::map usage.
28 /// The API should looks closely like the builtin associative arrays.
29 /// O(lg(n)) insertion, removal, and search time.
30 /// `Map` is designed to operate even without initialization through `makeMap`.
31 struct Map(K, V, alias less = "a < b", bool allowDuplicates = false)
32 {
33 public:
34 nothrow:
35 @nogc:
36 
37     this(int dummy)
38     {
39         lazyInitialize();
40     }
41 
42     @disable this(this);
43 
44     ~this()
45     {
46         if (_rbt !is null)
47         {
48             destroyFree(_rbt);
49             _rbt = null;
50         }
51     }
52 
53     /// Insert an element in the container, if the container doesn't already contain 
54     /// an element with equivalent key. 
55     /// Returns: `true` if the insertion took place.
56     bool insert(K key, V value)
57     {
58         lazyInitialize();
59 
60         auto kv = KeyValue(key, value);
61         assert(_rbt);
62         return _rbt.insert(kv) != 0;
63     }
64 
65     /// Removes an element from the container.
66     /// Returns: `true` if the removal took place.
67     bool remove(K key)
68     {
69         if (!isInitialized)
70             return false;
71 
72         auto kv = KeyValue(key, V.init);
73         return _rbt.removeKey(kv) != 0;
74     }
75 
76     /// Removes all elements from the map.
77     void clearContents()
78     {
79         if (!isInitialized)
80             return;
81 
82         while(_rbt.length > 0)
83             _rbt.removeBack();
84     }
85 
86     /// Returns: A pointer to the value corresponding to this key, or null if not available.
87     ///          Live builtin associative arrays.
88     inout(V)* opBinaryRight(string op)(K key) inout if (op == "in")
89     {
90         if (!isInitialized)
91             return null;
92 
93         auto kv = KeyValue(key, V.init);
94         auto node = _rbt._find(kv);
95         if (node is null)
96             return null;
97         else
98             return &node.value.value;
99     }
100 
101     /// Returns: A reference to the value corresponding to this key.
102     ref inout(V) opIndex(K key) inout
103     {
104         inout(V)* p = key in this;
105         return *p;
106     }
107 
108     /// Updates a value associated with a key, creates it if necessary.
109     void opIndexAssign(V value, K key)
110     {
111         // PERF: this could be faster
112         V* p = key in this;
113         if (p is null)
114             insert(key, value);
115         else
116             *p = value;
117     }
118 
119     /// Returns: `true` if this key is contained.
120     bool contains(K key) const
121     {
122          if (!isInitialized)
123             return false;
124         auto kv = KeyValue(key, V.init);
125         return (kv in _rbt);
126     }
127 
128     /// Returns: Number of elements in the map.
129     size_t length() const
130     {
131         if (!isInitialized)
132             return 0;
133 
134         return _rbt.length();
135     }
136 
137     /// Returns: `ttue` is the map has no element.
138     bool empty() const
139     {
140         if (!isInitialized)
141             return true;
142         return _rbt.length() == 0;
143     }
144 
145     // Iterate by value only
146 
147     /// Fetch a forward range on all values.
148     Range!(MapRangeType.value) byValue()
149     {
150         if (!isInitialized)
151             return Range!(MapRangeType.value).init;
152 
153         return Range!(MapRangeType.value)(_rbt[]);
154     }
155 
156     /// ditto
157     ConstRange!(MapRangeType.value) byValue() const
158     {
159         if (!isInitialized)
160             return ConstRange!(MapRangeType.value).init;
161 
162         return ConstRange!(MapRangeType.value)(_rbt[]);
163     }
164 
165     /// ditto
166     ImmutableRange!(MapRangeType.value) byValue() immutable
167     {
168         if (!isInitialized)
169             return ImmutableRange!(MapRangeType.value).init;
170         
171         return ImmutableRange!(MapRangeType.value)(_rbt[]);
172     }
173 
174     // default opSlice is like byValue for builtin associative arrays
175     alias opSlice = byValue;
176 
177     // Iterate by key only
178 
179     /// Fetch a forward range on all keys.
180     Range!(MapRangeType.key) byKey()
181     {
182         if (!isInitialized)
183             return Range!(MapRangeType.key).init;
184 
185         return Range!(MapRangeType.key)(_rbt[]);
186     }
187 
188     /// ditto
189     ConstRange!(MapRangeType.key) byKey() const
190     {
191         if (!isInitialized)
192             return ConstRange!(MapRangeType.key).init;
193 
194         return ConstRange!(MapRangeType.key)(_rbt[]);
195     }
196 
197     /// ditto
198     ImmutableRange!(MapRangeType.key) byKey() immutable
199     {
200         if (!isInitialized)
201             return ImmutableRange!(MapRangeType.key).init;
202 
203         return ImmutableRange!(MapRangeType.key)(_rbt[]);
204     }
205 
206     // Iterate by key-value
207 
208     /// Fetch a forward range on all keys.
209     Range!(MapRangeType.keyValue) byKeyValue()
210     {
211         if (!isInitialized)
212             return Range!(MapRangeType.keyValue).init;
213 
214         return Range!(MapRangeType.keyValue)(_rbt[]);
215     }
216 
217     /// ditto
218     ConstRange!(MapRangeType.keyValue) byKeyValue() const
219     {
220         if (!isInitialized)
221             return ConstRange!(MapRangeType.keyValue).init;
222 
223         return ConstRange!(MapRangeType.keyValue)(_rbt[]);
224     }
225 
226     /// ditto
227     ImmutableRange!(MapRangeType.keyValue) byKeyValue() immutable
228     {
229         if (!isInitialized)
230             return ImmutableRange!(MapRangeType.keyValue).init;
231 
232         return ImmutableRange!(MapRangeType.keyValue)(_rbt[]);
233     }
234 
235     // Iterate by single value (return a range where all elements have equal key)
236 
237     /// Fetch a forward range on all elements with given key.
238     Range!(MapRangeType.value) byGivenKey(K key)
239     {
240        if (!isInitialized)
241             return Range!(MapRangeType.value).init;
242 
243         auto kv = KeyValue(key, V.init);
244         return Range!(MapRangeType.value)(_rbt.range(kv));
245     }
246 
247     /// ditto
248     ConstRange!(MapRangeType.value) byGivenKey(K key) const
249     {
250         if (!isInitialized)
251             return ConstRange!(MapRangeType.value).init;
252 
253         auto kv = KeyValue(key, V.init);
254         return ConstRange!(MapRangeType.value)(_rbt.range(kv));
255     }
256 
257     /// ditto
258     ImmutableRange!(MapRangeType.value) byGivenKey(K key) immutable
259     {
260         if (!isInitialized)
261             return ImmutableRange!(MapRangeType.value).init;
262 
263         auto kv = KeyValue(key, V.init);
264         return ImmutableRange!(MapRangeType.value)(_rbt.range(kv));
265     }
266 
267 
268 private:
269 
270     alias Range(MapRangeType type) = MapRange!(RBNode!KeyValue*, type);
271     alias ConstRange(MapRangeType type) = MapRange!(const(RBNode!KeyValue)*, type); /// Ditto
272     alias ImmutableRange(MapRangeType type) = MapRange!(immutable(RBNode!KeyValue)*, type); /// Ditto
273 
274     alias _less = binaryFun!less;
275     static bool lessForAggregate(const(KeyValue) a, const(KeyValue) b)
276     {
277         return _less(a.key, b.key);
278     }
279 
280     alias InternalTree = RedBlackTree!(KeyValue, lessForAggregate, allowDuplicates);
281 
282     // we need a composite value to reuse Phobos RedBlackTree
283     static struct KeyValue
284     {
285     nothrow:
286     @nogc:
287         K key;
288         V value;
289     }
290 
291     InternalTree _rbt;
292 
293     bool isInitialized() const
294     {
295         return _rbt !is null;
296     }
297 
298     void lazyInitialize()
299     {
300         if (_rbt is null)
301         {
302             _rbt = mallocNew!InternalTree();
303         }
304     }
305 }
306 
307 unittest
308 {
309     // It should be possible to use most function of an uninitialized Map
310     // All except functions returning a range will work.
311     Map!(int, string) m;
312 
313     assert(m.length == 0);
314     assert(m.empty);
315     assert(!m.contains(7));
316 
317     auto range = m.byKey();
318     assert(range.empty);
319     foreach(e; range)
320     {        
321     }
322 
323     m[1] = "fun";
324 }
325 
326 unittest
327 {
328     void test(bool removeKeys) nothrow @nogc
329     {
330         {
331             auto test = makeMap!(int, string);
332             int N = 100;
333             foreach(i; 0..N)
334             {
335                 int key = (i * 69069) % 65536;
336                 test.insert(key, "this is a test");
337             }
338             foreach(i; 0..N)
339             {
340                 int key = (i * 69069) % 65536;
341                 assert(test.contains(key));
342             }
343         
344             if (removeKeys)
345             {
346                 foreach(i; 0..N)
347                 {
348                     int key = (i * 69069) % 65536;
349                     test.remove(key);
350                 }
351             }
352             foreach(i; 0..N)
353             {
354                 int key = (i * 69069) % 65536;
355                 assert(removeKeys ^ test.contains(key)); // either keys are here or removed
356             }            
357         }
358     }
359     test(true);
360     test(false);
361 }
362 
363 unittest
364 {
365     Map!(string, int) aa = makeMap!(string, int);   // Associative array of ints that are
366     // indexed by string keys.
367     // The KeyType is string.
368     aa["hello"] = 3;  // set value associated with key "hello" to 3
369     int value = aa["hello"];  // lookup value from a key
370     assert(value == 3);    
371 
372     int* p;
373 
374     p = ("hello" in aa);
375     if (p !is null)
376     {
377         *p = 4;  // update value associated with key
378         assert(aa["hello"] == 4);
379     }
380 
381     aa.remove("hello");
382 }
383 
384 /// Creates a new empty `Set`.
385 Set!(K, less) makeSet(K, alias less = "a < b", bool allowDuplicates = false)()
386 {
387     return Set!(K, less, allowDuplicates)(42);
388 }
389 
390 
391 /// Set, designed to replace std::set usage.
392 /// O(lg(n)) insertion, removal, and search time.
393 /// `Set` is designed to operate even without initialization through `makeSet`.
394 struct Set(K, alias less = "a < b", bool allowDuplicates = false)
395 {
396 public:
397 nothrow:
398 @nogc:
399 
400     this(int dummy)
401     {
402          lazyInitialize();
403     }
404 
405     @disable this(this);
406 
407     ~this()
408     {
409         if (isInitialized)
410         {
411             destroyFree(_rbt);
412             _rbt = null;
413         }
414     }
415 
416     /// Insert an element in the container. 
417     /// If allowDuplicates is false, this can fail and return `false` 
418     /// if the already contains an element with equivalent key. 
419     /// Returns: `true` if the insertion took place.
420     bool insert(K key)
421     {
422         lazyInitialize();
423         return _rbt.insert(key) != 0;
424     }
425 
426     /// Removes an element from the container.
427     /// Returns: `true` if the removal took place.
428     bool remove(K key)
429     {
430         if (!isInitialized)
431             return false;
432         return _rbt.removeKey(key) != 0;
433     }
434 
435     /// Removes all elements from the set.
436     void clearContents()
437     {
438         if (!isInitialized)
439             return;
440         while(_rbt.length > 0)
441             _rbt.removeBack();
442     }
443 
444     /// Returns: `true` if the element is present.
445     bool opBinaryRight(string op)(K key) inout if (op == "in")
446     {
447         if (!isInitialized)
448             return false;
449         return key in _rbt;
450     }
451 
452     /// Returns: `true` if the element is present.
453     bool opIndex(K key) const
454     {
455         if (!isInitialized)
456             return false;
457         return key in _rbt;
458     }
459 
460     /// Returns: `true` if the element is present.
461     bool contains(K key) const
462     {
463         if (!isInitialized)
464             return false;
465         return key in _rbt;
466     }
467 
468     /// Fetch a range that spans all the elements in the container.
469     auto opSlice() inout
470     {
471         if (!isInitialized)
472             return nullRange();
473         return _rbt[];
474     }
475 
476     /// Returns: Number of elements in the set.
477     size_t length() const
478     {
479         if (!isInitialized)
480             return 0;
481         return _rbt.length();
482     }
483 
484     /// Returns: `ttue` is the set has no element.
485     bool empty() const
486     {
487         if (!isInitialized)
488             return true;
489         return _rbt.length() == 0;
490     }
491 
492 private:
493     alias InternalTree = RedBlackTree!(K, less, allowDuplicates); 
494     InternalTree _rbt;
495 
496     bool isInitialized() const
497     {
498         return _rbt !is null;
499     }
500 
501     void lazyInitialize()
502     {
503         if (_rbt is null)
504         {
505             _rbt = mallocNew!InternalTree();
506         }
507     }
508 
509     /**
510     * Return a range without any items.
511     */
512     auto nullRange()
513     {
514         return InternalTree.Range.init;
515     }
516 
517     /// Ditto
518     auto nullRange() const
519     {
520         return InternalTree.ConstRange.init;
521     }
522 
523     /// Ditto
524     auto nullRange() immutable
525     {
526         return InternalTree.ImmutableRange.init;
527     }
528 }
529 
530 unittest
531 {
532     // It should be possible to use most function of an uninitialized Set
533     // All except functions returning a range will work.
534     Set!(string) set;
535 
536     assert(set.length == 0);
537     assert(set.empty);
538     set.clearContents();
539     assert(!set.contains("toto"));
540 
541     auto range = set[];
542     assert(range.empty);
543     foreach(e; range)
544     {        
545     }
546 
547     // Finally create the internal state
548     set.insert("titi");
549     assert(set.contains("titi"));
550 }
551 
552 
553 unittest
554 {
555     {
556         Set!(string) keywords = makeSet!string;
557 
558         assert(keywords.insert("public"));
559         assert(keywords.insert("private"));
560         assert(!keywords.insert("private"));
561 
562         assert(keywords.remove("public"));
563         assert(!keywords.remove("non-existent"));
564 
565         assert(keywords.contains("private"));
566         assert(!keywords.contains("public"));
567     }
568 
569 }
570 
571 private:
572 
573 
574 /*
575 * Implementation for a Red Black node for use in a Red Black Tree (see below)
576 *
577 * this implementation assumes we have a marker Node that is the parent of the
578 * root Node.  This marker Node is not a valid Node, but marks the end of the
579 * collection.  The root is the left child of the marker Node, so it is always
580 * last in the collection.  The marker Node is passed in to the setColor
581 * function, and the Node which has this Node as its parent is assumed to be
582 * the root Node.
583 *
584 * A Red Black tree should have O(lg(n)) insertion, removal, and search time.
585 */
586 struct RBNode(V)
587 {
588 nothrow:
589 @nogc:
590     /*
591     * Convenience alias
592     */
593     alias Node = RBNode*;
594 
595     private Node _left;
596     private Node _right;
597     private Node _parent;
598 
599     /**
600     * The value held by this node
601     */
602     V value;
603 
604     /**
605     * Enumeration determining what color the node is.  Null nodes are assumed
606     * to be black.
607     */
608     enum Color : byte
609     {
610         Red,
611         Black
612     }
613 
614     /**
615     * The color of the node.
616     */
617     Color color;
618 
619     /**
620     * Get the left child
621     */
622     @property inout(RBNode)* left() inout
623     {
624         return _left;
625     }
626 
627     /**
628     * Get the right child
629     */
630     @property inout(RBNode)* right() inout
631     {
632         return _right;
633     }
634 
635     /**
636     * Get the parent
637     */
638     @property inout(RBNode)* parent() inout
639     {
640         return _parent;
641     }
642 
643     void deallocate()
644     {
645         //import core.stdc.stdio;
646         //printf("deallocate %p\n", &this);
647         destroyFree(&this);
648     }
649 
650     /**
651     * Set the left child.  Also updates the new child's parent node.  This
652     * does not update the previous child.
653     *
654     * Returns newNode
655     */
656     @property Node left(Node newNode)
657     {
658         _left = newNode;
659         if (newNode !is null)
660             newNode._parent = &this;
661         return newNode;
662     }
663 
664     /**
665     * Set the right child.  Also updates the new child's parent node.  This
666     * does not update the previous child.
667     *
668     * Returns newNode
669     */
670     @property Node right(Node newNode)
671     {
672         _right = newNode;
673         if (newNode !is null)
674             newNode._parent = &this;
675         return newNode;
676     }
677 
678     // assume _left is not null
679     //
680     // performs rotate-right operation, where this is T, _right is R, _left is
681     // L, _parent is P:
682     //
683     //      P         P
684     //      |   ->    |
685     //      T         L
686     //     / \       / \
687     //    L   R     a   T
688     //   / \           / \
689     //  a   b         b   R
690     //
691     /**
692     * Rotate right.  This performs the following operations:
693     *  - The left child becomes the parent of this node.
694     *  - This node becomes the new parent's right child.
695     *  - The old right child of the new parent becomes the left child of this
696     *    node.
697     */
698     Node rotateR()
699     in
700     {
701         assert(_left !is null);
702     }
703     body
704     {
705         // sets _left._parent also
706         if (isLeftNode)
707             parent.left = _left;
708         else
709             parent.right = _left;
710         Node tmp = _left._right;
711 
712         // sets _parent also
713         _left.right = &this;
714 
715         // sets tmp._parent also
716         left = tmp;
717 
718         return &this;
719     }
720 
721     // assumes _right is non null
722     //
723     // performs rotate-left operation, where this is T, _right is R, _left is
724     // L, _parent is P:
725     //
726     //      P           P
727     //      |    ->     |
728     //      T           R
729     //     / \         / \
730     //    L   R       T   b
731     //       / \     / \
732     //      a   b   L   a
733     //
734     /**
735     * Rotate left.  This performs the following operations:
736     *  - The right child becomes the parent of this node.
737     *  - This node becomes the new parent's left child.
738     *  - The old left child of the new parent becomes the right child of this
739     *    node.
740     */
741     Node rotateL()
742     in
743     {
744         assert(_right !is null);
745     }
746     body
747     {
748         // sets _right._parent also
749         if (isLeftNode)
750             parent.left = _right;
751         else
752             parent.right = _right;
753         Node tmp = _right._left;
754 
755         // sets _parent also
756         _right.left = &this;
757 
758         // sets tmp._parent also
759         right = tmp;
760         return &this;
761     }
762 
763 
764     /**
765     * Returns true if this node is a left child.
766     *
767     * Note that this should always return a value because the root has a
768     * parent which is the marker node.
769     */
770     @property bool isLeftNode() const
771         in
772         {
773             assert(_parent !is null);
774         }
775     body
776     {
777         return _parent._left is &this;
778     }
779 
780     /**
781     * Set the color of the node after it is inserted.  This performs an
782     * update to the whole tree, possibly rotating nodes to keep the Red-Black
783     * properties correct.  This is an O(lg(n)) operation, where n is the
784     * number of nodes in the tree.
785     *
786     * end is the marker node, which is the parent of the topmost valid node.
787     */
788     void setColor(Node end)
789     {
790         // test against the marker node
791         if (_parent !is end)
792         {
793             if (_parent.color == Color.Red)
794             {
795                 Node cur = &this;
796                 while (true)
797                 {
798                     // because root is always black, _parent._parent always exists
799                     if (cur._parent.isLeftNode)
800                     {
801                         // parent is left node, y is 'uncle', could be null
802                         Node y = cur._parent._parent._right;
803                         if (y !is null && y.color == Color.Red)
804                         {
805                             cur._parent.color = Color.Black;
806                             y.color = Color.Black;
807                             cur = cur._parent._parent;
808                             if (cur._parent is end)
809                             {
810                                 // root node
811                                 cur.color = Color.Black;
812                                 break;
813                             }
814                             else
815                             {
816                                 // not root node
817                                 cur.color = Color.Red;
818                                 if (cur._parent.color == Color.Black)
819                                     // satisfied, exit the loop
820                                     break;
821                             }
822                         }
823                         else
824                         {
825                             if (!cur.isLeftNode)
826                                 cur = cur._parent.rotateL();
827                             cur._parent.color = Color.Black;
828                             cur = cur._parent._parent.rotateR();
829                             cur.color = Color.Red;
830                             // tree should be satisfied now
831                             break;
832                         }
833                     }
834                     else
835                     {
836                         // parent is right node, y is 'uncle'
837                         Node y = cur._parent._parent._left;
838                         if (y !is null && y.color == Color.Red)
839                         {
840                             cur._parent.color = Color.Black;
841                             y.color = Color.Black;
842                             cur = cur._parent._parent;
843                             if (cur._parent is end)
844                             {
845                                 // root node
846                                 cur.color = Color.Black;
847                                 break;
848                             }
849                             else
850                             {
851                                 // not root node
852                                 cur.color = Color.Red;
853                                 if (cur._parent.color == Color.Black)
854                                     // satisfied, exit the loop
855                                     break;
856                             }
857                         }
858                         else
859                         {
860                             if (cur.isLeftNode)
861                                 cur = cur._parent.rotateR();
862                             cur._parent.color = Color.Black;
863                             cur = cur._parent._parent.rotateL();
864                             cur.color = Color.Red;
865                             // tree should be satisfied now
866                             break;
867                         }
868                     }
869                 }
870 
871             }
872         }
873         else
874         {
875             //
876             // this is the root node, color it black
877             //
878             color = Color.Black;
879         }
880     }
881 
882     /**
883     * Remove this node from the tree.  The 'end' node is used as the marker
884     * which is root's parent.  Note that this cannot be null!
885     *
886     * Returns the next highest valued node in the tree after this one, or end
887     * if this was the highest-valued node.
888     */
889     Node remove(Node end)
890     {
891         //
892         // remove this node from the tree, fixing the color if necessary.
893         //
894         Node x;
895         Node ret = next;
896 
897         // if this node has 2 children
898         if (_left !is null && _right !is null)
899         {
900             //
901             // normally, we can just swap this node's and y's value, but
902             // because an iterator could be pointing to y and we don't want to
903             // disturb it, we swap this node and y's structure instead.  This
904             // can also be a benefit if the value of the tree is a large
905             // struct, which takes a long time to copy.
906             //
907             Node yp, yl, yr;
908             Node y = ret; // y = next
909             yp = y._parent;
910             yl = y._left;
911             yr = y._right;
912             auto yc = y.color;
913             auto isyleft = y.isLeftNode;
914 
915             //
916             // replace y's structure with structure of this node.
917             //
918             if (isLeftNode)
919                 _parent.left = y;
920             else
921                 _parent.right = y;
922             //
923             // need special case so y doesn't point back to itself
924             //
925             y.left = _left;
926             if (_right is y)
927                 y.right = &this;
928             else
929                 y.right = _right;
930             y.color = color;
931 
932             //
933             // replace this node's structure with structure of y.
934             //
935             left = yl;
936             right = yr;
937             if (_parent !is y)
938             {
939                 if (isyleft)
940                     yp.left = &this;
941                 else
942                     yp.right = &this;
943             }
944             color = yc;
945         }
946 
947         // if this has less than 2 children, remove it
948         if (_left !is null)
949             x = _left;
950         else
951             x = _right;
952 
953         bool deferedUnlink = false;
954         if (x is null)
955         {
956             // pretend this is a null node, defer unlinking the node
957             x = &this;
958             deferedUnlink = true;
959         }
960         else if (isLeftNode)
961             _parent.left = x;
962         else
963             _parent.right = x;
964 
965         // if the color of this is black, then it needs to be fixed
966         if (color == color.Black)
967         {
968             // need to recolor the tree.
969             while (x._parent !is end && x.color == Node.Color.Black)
970             {
971                 if (x.isLeftNode)
972                 {
973                     // left node
974                     Node w = x._parent._right;
975                     if (w.color == Node.Color.Red)
976                     {
977                         w.color = Node.Color.Black;
978                         x._parent.color = Node.Color.Red;
979                         x._parent.rotateL();
980                         w = x._parent._right;
981                     }
982                     Node wl = w.left;
983                     Node wr = w.right;
984                     if ((wl is null || wl.color == Node.Color.Black) &&
985                         (wr is null || wr.color == Node.Color.Black))
986                     {
987                         w.color = Node.Color.Red;
988                         x = x._parent;
989                     }
990                     else
991                     {
992                         if (wr is null || wr.color == Node.Color.Black)
993                         {
994                             // wl cannot be null here
995                             wl.color = Node.Color.Black;
996                             w.color = Node.Color.Red;
997                             w.rotateR();
998                             w = x._parent._right;
999                         }
1000 
1001                         w.color = x._parent.color;
1002                         x._parent.color = Node.Color.Black;
1003                         w._right.color = Node.Color.Black;
1004                         x._parent.rotateL();
1005                         x = end.left; // x = root
1006                     }
1007                 }
1008                 else
1009                 {
1010                     // right node
1011                     Node w = x._parent._left;
1012                     if (w.color == Node.Color.Red)
1013                     {
1014                         w.color = Node.Color.Black;
1015                         x._parent.color = Node.Color.Red;
1016                         x._parent.rotateR();
1017                         w = x._parent._left;
1018                     }
1019                     Node wl = w.left;
1020                     Node wr = w.right;
1021                     if ((wl is null || wl.color == Node.Color.Black) &&
1022                         (wr is null || wr.color == Node.Color.Black))
1023                     {
1024                         w.color = Node.Color.Red;
1025                         x = x._parent;
1026                     }
1027                     else
1028                     {
1029                         if (wl is null || wl.color == Node.Color.Black)
1030                         {
1031                             // wr cannot be null here
1032                             wr.color = Node.Color.Black;
1033                             w.color = Node.Color.Red;
1034                             w.rotateL();
1035                             w = x._parent._left;
1036                         }
1037 
1038                         w.color = x._parent.color;
1039                         x._parent.color = Node.Color.Black;
1040                         w._left.color = Node.Color.Black;
1041                         x._parent.rotateR();
1042                         x = end.left; // x = root
1043                     }
1044                 }
1045             }
1046             x.color = Node.Color.Black;
1047         }
1048 
1049         if (deferedUnlink)
1050         {
1051             //
1052             // unlink this node from the tree
1053             //
1054             if (isLeftNode)
1055                 _parent.left = null;
1056             else
1057                 _parent.right = null;
1058         }
1059 
1060         // clean references to help GC - Bugzilla 12915
1061         _left = _right = _parent = null;
1062 
1063         return ret;
1064     }
1065 
1066     /**
1067     * Return the leftmost descendant of this node.
1068     */
1069     @property inout(RBNode)* leftmost() inout
1070     {
1071         inout(RBNode)* result = &this;
1072         while (result._left !is null)
1073             result = result._left;
1074         return result;
1075     }
1076 
1077     /**
1078     * Return the rightmost descendant of this node
1079     */
1080     @property inout(RBNode)* rightmost() inout
1081     {
1082         inout(RBNode)* result = &this;
1083         while (result._right !is null)
1084             result = result._right;
1085         return result;
1086     }
1087 
1088     /**
1089     * Returns the next valued node in the tree.
1090     *
1091     * You should never call this on the marker node, as it is assumed that
1092     * there is a valid next node.
1093     */
1094     @property inout(RBNode)* next() inout
1095     {
1096         inout(RBNode)* n = &this;
1097         if (n.right is null)
1098         {
1099             while (!n.isLeftNode)
1100                 n = n._parent;
1101             return n._parent;
1102         }
1103         else
1104             return n.right.leftmost;
1105     }
1106 
1107     /**
1108     * Returns the previous valued node in the tree.
1109     *
1110     * You should never call this on the leftmost node of the tree as it is
1111     * assumed that there is a valid previous node.
1112     */
1113     @property inout(RBNode)* prev() inout
1114     {
1115         inout(RBNode)* n = &this;
1116         if (n.left is null)
1117         {
1118             while (n.isLeftNode)
1119                 n = n._parent;
1120             return n._parent;
1121         }
1122         else
1123             return n.left.rightmost;
1124     }
1125 }
1126 
1127 // Range type for RedBlackTree
1128 private struct RBRange(N)
1129 {
1130 nothrow:
1131 @nogc:
1132     alias Node = N;
1133     alias Elem = typeof(Node.value);
1134 
1135     private Node _begin = null;
1136     private Node _end = null;
1137 
1138     private this(Node b, Node e)
1139     {
1140         _begin = b;
1141         _end = e;
1142     }
1143 
1144     /**
1145     * Returns $(D true) if the range is _empty
1146     */
1147     @property bool empty() const
1148     {
1149         return _begin is _end;
1150     }
1151 
1152     /**
1153     * Returns the first element in the range
1154     */
1155     @property Elem front()
1156     {
1157         return _begin.value;
1158     }
1159 
1160     /**
1161     * Returns the last element in the range
1162     */
1163     @property Elem back()
1164     {
1165         return _end.prev.value;
1166     }
1167 
1168     /**
1169     * pop the front element from the range
1170     *
1171     * complexity: amortized $(BIGOH 1)
1172     */
1173     void popFront()
1174     {
1175         _begin = _begin.next;
1176     }
1177 
1178     /**
1179     * pop the back element from the range
1180     *
1181     * complexity: amortized $(BIGOH 1)
1182     */
1183     void popBack()
1184     {
1185         _end = _end.prev;
1186     }
1187 
1188     /**
1189     * Trivial _save implementation, needed for $(D isForwardRange).
1190     */
1191     @property RBRange save()
1192     {
1193         return this;
1194     }
1195 }
1196 
1197 unittest
1198 {
1199     // RBRange.init is supposed to be an empty valid range
1200     RBRange!(RBNode!int*) range;
1201     assert(range.empty);
1202     foreach(e; range)
1203     {        
1204     }
1205 }
1206 
1207 private enum MapRangeType
1208 {
1209     key,
1210     value,
1211     keyValue
1212 }
1213 
1214 // Range type for Dplug's Map, can iterate on keys or values
1215 private struct MapRange(N, MapRangeType type)
1216 {
1217 nothrow:
1218 @nogc:
1219 
1220     alias Node = N;
1221     alias InnerRange = RBRange!N;
1222 
1223     static if (type == MapRangeType.key)
1224         alias Elem = typeof(Node.value.key);
1225 
1226     else static if (type == MapRangeType.value)
1227         alias Elem = typeof(Node.value.value);
1228 
1229     else static if (type == MapRangeType.keyValue)
1230         alias Elem = typeof(Node.value);
1231 
1232     static Elem get(InnerRange.Elem pair)
1233     {
1234         static if (type == MapRangeType.key)
1235             return pair.key;
1236 
1237         else static if (type == MapRangeType.value)
1238             return pair.value;
1239 
1240         else static if (type == MapRangeType.keyValue)
1241             return pair;
1242     }
1243 
1244     // A Map range is just a wrapper around a RBRange
1245     private InnerRange _inner;
1246 
1247     private this(InnerRange inner)
1248     {
1249         _inner = inner;
1250     }
1251 
1252     /**
1253     * Returns $(D true) if the range is _empty
1254     */
1255     @property bool empty() const
1256     {
1257         return _inner.empty;
1258     }
1259 
1260     /**
1261     * Returns the first element in the range
1262     */
1263     @property Elem front()
1264     {
1265         return get(_inner.front);
1266     }
1267 
1268     /**
1269     * Returns the last element in the range
1270     */
1271     @property Elem back()
1272     {
1273         return get(_inner.back());
1274     }
1275 
1276     /**
1277     * pop the front element from the range
1278     *
1279     * complexity: amortized $(BIGOH 1)
1280     */
1281     void popFront()
1282     {
1283         _inner.popFront();
1284     }
1285 
1286     /**
1287     * pop the back element from the range
1288     *
1289     * complexity: amortized $(BIGOH 1)
1290     */
1291     void popBack()
1292     {
1293         _inner.popBack();
1294     }
1295 
1296     /**
1297     * Trivial _save implementation, needed for $(D isForwardRange).
1298     */
1299     @property MapRange save()
1300     {
1301         return this;
1302     }
1303 }
1304 
1305 /**
1306 * Implementation of a $(LINK2 https://en.wikipedia.org/wiki/Red%E2%80%93black_tree,
1307 * red-black tree) container.
1308 *
1309 * All inserts, removes, searches, and any function in general has complexity
1310 * of $(BIGOH lg(n)).
1311 *
1312 * To use a different comparison than $(D "a < b"), pass a different operator string
1313 * that can be used by $(REF binaryFun, std,functional), or pass in a
1314 * function, delegate, functor, or any type where $(D less(a, b)) results in a $(D bool)
1315 * value.
1316 *
1317 * Note that less should produce a strict ordering.  That is, for two unequal
1318 * elements $(D a) and $(D b), $(D less(a, b) == !less(b, a)). $(D less(a, a)) should
1319 * always equal $(D false).
1320 *
1321 * If $(D allowDuplicates) is set to $(D true), then inserting the same element more than
1322 * once continues to add more elements.  If it is $(D false), duplicate elements are
1323 * ignored on insertion.  If duplicates are allowed, then new elements are
1324 * inserted after all existing duplicate elements.
1325 */
1326 
1327 final class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
1328 {
1329 nothrow:
1330 @nogc:
1331     /**
1332     * Element type for the tree
1333     */
1334     alias Elem = T;
1335 
1336     alias _less = binaryFun!less;
1337 
1338     // used for convenience
1339     private alias RBNode = .RBNode!Elem;
1340     private alias Node = RBNode.Node;
1341 
1342     private Node   _end;
1343     private Node   _begin;
1344     private size_t _length;
1345 
1346     private void _setup()
1347     {
1348         assert(!_end); //Make sure that _setup isn't run more than once.
1349         _begin = _end = allocate();
1350     }
1351 
1352     static private Node allocate()
1353     {
1354         Node p = mallocNew!RBNode;
1355         //import core.stdc.stdio;
1356         //printf("allocate %p\n", p);
1357         return p;
1358     }
1359 
1360     static private Node allocate(Elem v)
1361     {
1362         auto result = allocate();
1363         result.value = v;
1364         return result;
1365     }
1366 
1367     /**
1368     * The range types for $(D RedBlackTree)
1369     */
1370     alias Range = RBRange!(RBNode*);
1371     alias ConstRange = RBRange!(const(RBNode)*); /// Ditto
1372     alias ImmutableRange = RBRange!(immutable(RBNode)*); /// Ditto
1373 
1374     // find a node based on an element value
1375     private inout(RBNode)* _find(Elem e) inout
1376     {
1377         static if (allowDuplicates)
1378         {
1379             inout(RBNode)* cur = _end.left;
1380             inout(RBNode)* result = null;
1381             while (cur)
1382             {
1383                 if (_less(cur.value, e))
1384                     cur = cur.right;
1385                 else if (_less(e, cur.value))
1386                     cur = cur.left;
1387                 else
1388                 {
1389                     // want to find the left-most element
1390                     result = cur;
1391                     cur = cur.left;
1392                 }
1393             }
1394             return result;
1395         }
1396         else
1397         {
1398             inout(RBNode)* cur = _end.left;
1399             while (cur)
1400             {
1401                 if (_less(cur.value, e))
1402                     cur = cur.right;
1403                 else if (_less(e, cur.value))
1404                     cur = cur.left;
1405                 else
1406                     return cur;
1407             }
1408             return null;
1409         }
1410     }
1411 
1412     // add an element to the tree, returns the node added, or the existing node
1413     // if it has already been added and allowDuplicates is false
1414     private auto _add(Elem n)
1415     {
1416         Node result;
1417         static if (!allowDuplicates)
1418             bool added = true;
1419 
1420         if (!_end.left)
1421         {
1422             _end.left = _begin = result = allocate(n);
1423         }
1424         else
1425         {
1426             Node newParent = _end.left;
1427             Node nxt;
1428             while (true)
1429             {
1430                 if (_less(n, newParent.value))
1431                 {
1432                     nxt = newParent.left;
1433                     if (nxt is null)
1434                     {
1435                         //
1436                         // add to right of new parent
1437                         //
1438                         newParent.left = result = allocate(n);
1439                         break;
1440                     }
1441                 }
1442                 else
1443                 {
1444                     static if (!allowDuplicates)
1445                     {
1446                         if (!(_less(newParent.value, n)))
1447                         {
1448                             result = newParent;
1449                             added = false;
1450                             break;
1451                         }
1452                     }
1453                     nxt = newParent.right;
1454                     if (nxt is null)
1455                     {
1456                         //
1457                         // add to right of new parent
1458                         //
1459                         newParent.right = result = allocate(n);
1460                         break;
1461                     }
1462                 }
1463                 newParent = nxt;
1464             }
1465             if (_begin.left)
1466                 _begin = _begin.left;
1467         }
1468 
1469         static if (allowDuplicates)
1470         {
1471             result.setColor(_end);
1472             ++_length;
1473             return result;
1474         }
1475         else
1476         {
1477             import std.typecons : Tuple;
1478 
1479             if (added)
1480             {
1481                 ++_length;
1482                 result.setColor(_end);
1483             }
1484             return Tuple!(bool, "added", Node, "n")(added, result);
1485         }
1486     }
1487 
1488 
1489     /**
1490     * Check if any elements exist in the container.  Returns $(D false) if at least
1491     * one element exists.
1492     */
1493     @property bool empty()
1494     {
1495         return _end.left is null;
1496     }
1497 
1498     /++
1499     Returns the number of elements in the container.
1500 
1501     Complexity: $(BIGOH 1).
1502     +/
1503     @property size_t length() const
1504     {
1505         return _length;
1506     }
1507 
1508     // Find the range for which every element is equal.
1509     private void findEnclosingRange(Elem e, inout(RBNode)** begin, inout(RBNode)** end) inout
1510     {
1511         *begin = _firstGreaterEqual(e);
1512         *end = _firstGreater(e);
1513     }
1514 
1515     /**
1516     * Fetch a range that spans all the elements in the container.
1517     *
1518     * Complexity: $(BIGOH 1)
1519     */
1520     Range opSlice()
1521     {
1522         return Range(_begin, _end);
1523     }
1524 
1525     /// Ditto
1526     ConstRange opSlice() const
1527     {
1528         return ConstRange(_begin, _end);
1529     }
1530 
1531     /// Ditto
1532     ImmutableRange opSlice() immutable
1533     {
1534         return ImmutableRange(_begin, _end);
1535     }
1536 
1537     /**
1538     * Fetch a range that spans all equal elements of a particular value.
1539     *
1540     * Complexity: $(BIGOH 1)
1541     */
1542     Range range(Elem e)
1543     {
1544         RBNode* begin, end;
1545         findEnclosingRange(e, &begin, &end);
1546         return Range(begin, end);
1547     }
1548 
1549     /// Ditto
1550     ConstRange range(Elem e) const
1551     {
1552         const(RBNode)* begin, end;
1553         findEnclosingRange(e, &begin, &end);
1554         return ConstRange(begin, end);
1555     }
1556 
1557     /// Ditto
1558     ImmutableRange range(Elem e) immutable
1559     {
1560         immutable(RBNode)* begin, end;
1561         findEnclosingRange(e, &begin, &end);
1562         return ImmutableRange(begin, end);
1563     }
1564 
1565     /**
1566     * The front element in the container
1567     *
1568     * Complexity: $(BIGOH 1)
1569     */
1570     Elem front()
1571     {
1572         return _begin.value;
1573     }
1574 
1575     /**
1576     * The last element in the container
1577     *
1578     * Complexity: $(BIGOH log(n))
1579     */
1580     Elem back()
1581     {
1582         return _end.prev.value;
1583     }
1584 
1585     /++
1586     $(D in) operator. Check to see if the given element exists in the
1587     container.
1588 
1589     Complexity: $(BIGOH log(n))
1590     +/
1591     bool opBinaryRight(string op)(Elem e) const if (op == "in")
1592     {
1593         return _find(e) !is null;
1594     }
1595 
1596     /**
1597     * Insert a single element in the container.  Note that this does not
1598     * invalidate any ranges currently iterating the container.
1599     *
1600     * Returns: The number of elements inserted.
1601     *
1602     * Complexity: $(BIGOH log(n))
1603     */
1604     size_t stableInsert(Elem elem)
1605     {
1606         static if (allowDuplicates)
1607         {
1608             _add(elem);
1609             return 1;
1610         }
1611         else
1612         {
1613             return(_add(elem).added ? 1 : 0);
1614         }
1615     }
1616 
1617     /// ditto
1618     alias insert = stableInsert;
1619 
1620     /**
1621     * Remove an element from the container and return its value.
1622     *
1623     * Complexity: $(BIGOH log(n))
1624     */
1625     Elem removeAny()
1626     {
1627         scope(success)
1628             --_length;
1629         auto n = _begin;
1630         auto result = n.value;
1631         _begin = n.remove(_end);
1632         n.deallocate();
1633         return result;
1634     }
1635 
1636     /**
1637     * Remove the front element from the container.
1638     *
1639     * Complexity: $(BIGOH log(n))
1640     */
1641     void removeFront()
1642     {
1643         scope(success)
1644             --_length;
1645         auto oldBegin = _begin;
1646         _begin = _begin.remove(_end);
1647         oldBegin.deallocate();
1648     }
1649 
1650     /**
1651     * Remove the back element from the container.
1652     *
1653     * Complexity: $(BIGOH log(n))
1654     */
1655     void removeBack()
1656     {
1657         scope(success)
1658             --_length;
1659         auto lastnode = _end.prev;
1660         if (lastnode is _begin)
1661         {
1662             auto oldBegin = _begin;
1663             _begin = _begin.remove(_end);
1664             oldBegin.deallocate();
1665         }
1666         else
1667         {
1668             lastnode.remove(_end);
1669             lastnode.deallocate();
1670         }
1671     }
1672 
1673     /++ Ditto +/
1674     size_t removeKey(Elem e)
1675     {
1676         immutable lenBefore = length;
1677 
1678         auto beg = _firstGreaterEqual(e);
1679         if (beg is _end || _less(e, beg.value))
1680             // no values are equal
1681             return 0;
1682         auto oldBeg = beg;
1683         immutable isBegin = (beg is _begin);
1684         beg = beg.remove(_end);
1685         if (isBegin)
1686             _begin = beg;
1687         --_length;
1688 
1689         oldBeg.deallocate();
1690 
1691         return lenBefore - length;
1692     }
1693 
1694     // find the first node where the value is > e
1695     private inout(RBNode)* _firstGreater(Elem e) inout
1696     {
1697         // can't use _find, because we cannot return null
1698         auto cur = _end.left;
1699         inout(RBNode)* result = _end;
1700         while (cur)
1701         {
1702             if (_less(e, cur.value))
1703             {
1704                 result = cur;
1705                 cur = cur.left;
1706             }
1707             else
1708                 cur = cur.right;
1709         }
1710         return result;
1711     }
1712 
1713 
1714     // find the first node where the value is >= e
1715     private inout(RBNode)* _firstGreaterEqual(Elem e) inout
1716     {
1717         // can't use _find, because we cannot return null.
1718         auto cur = _end.left;
1719         inout(RBNode)* result = _end;
1720         while (cur)
1721         {
1722             if (_less(cur.value, e))
1723                 cur = cur.right;
1724             else
1725             {
1726                 result = cur;
1727                 cur = cur.left;
1728             }
1729 
1730         }
1731         return result;
1732     }
1733 
1734     ///
1735     this()
1736     {
1737         _setup();
1738     }
1739 
1740     ~this()
1741     {
1742         while(length > 0)
1743             removeBack();
1744 
1745         // deallocate sentinel
1746         _end.deallocate();
1747     }
1748 }