| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | // Copyright ©2012 The bíogo Authors. All rights reserved.
 | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style
 | 
					
						
							|  |  |  | // license that can be found at the end of this file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Package tree implements Left-Leaning Red Black trees as described by Robert Sedgewick.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // More details relating to the implementation are available at the following locations:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
 | 
					
						
							|  |  |  | // http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
 | 
					
						
							|  |  |  | // http://www.teachsolaisgames.com/articles/balanced_left_leaning.html
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Heavily modified by Miek Gieben for use in DNS zones.
 | 
					
						
							|  |  |  | package tree
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 16:56:16 +01:00
										 |  |  | import "github.com/miekg/dns"
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | const (
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	td234 = iota
 | 
					
						
							|  |  |  | 	bu23
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Operation mode of the LLRB tree.
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | const mode = bu23
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func init() {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if mode != td234 && mode != bu23 {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		panic("tree: unknown mode")
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A Color represents the color of a Node.
 | 
					
						
							|  |  |  | type Color bool
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const (
 | 
					
						
							|  |  |  | 	// Red as false give us the defined behaviour that new nodes are red. Although this
 | 
					
						
							|  |  |  | 	// is incorrect for the root node, that is resolved on the first insertion.
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	red   Color = false
 | 
					
						
							|  |  |  | 	black Color = true
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A Node represents a node in the LLRB tree.
 | 
					
						
							|  |  |  | type Node struct {
 | 
					
						
							|  |  |  | 	Elem        *Elem
 | 
					
						
							|  |  |  | 	Left, Right *Node
 | 
					
						
							|  |  |  | 	Color       Color
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A Tree manages the root node of an LLRB tree. Public methods are exposed through this type.
 | 
					
						
							|  |  |  | type Tree struct {
 | 
					
						
							|  |  |  | 	Root  *Node // Root node of the tree.
 | 
					
						
							|  |  |  | 	Count int   // Number of elements stored.
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper methods
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // color returns the effect color of a Node. A nil node returns black.
 | 
					
						
							|  |  |  | func (n *Node) color() Color {
 | 
					
						
							|  |  |  | 	if n == nil {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 		return black
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 	return n.Color
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // (a,c)b -rotL-> ((a,)b,)c
 | 
					
						
							|  |  |  | func (n *Node) rotateLeft() (root *Node) {
 | 
					
						
							|  |  |  | 	// Assumes: n has two children.
 | 
					
						
							|  |  |  | 	root = n.Right
 | 
					
						
							|  |  |  | 	n.Right = root.Left
 | 
					
						
							|  |  |  | 	root.Left = n
 | 
					
						
							|  |  |  | 	root.Color = n.Color
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	n.Color = red
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // (a,c)b -rotR-> (,(,c)b)a
 | 
					
						
							|  |  |  | func (n *Node) rotateRight() (root *Node) {
 | 
					
						
							|  |  |  | 	// Assumes: n has two children.
 | 
					
						
							|  |  |  | 	root = n.Left
 | 
					
						
							|  |  |  | 	n.Left = root.Right
 | 
					
						
							|  |  |  | 	root.Right = n
 | 
					
						
							|  |  |  | 	root.Color = n.Color
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	n.Color = red
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // (aR,cR)bB -flipC-> (aB,cB)bR | (aB,cB)bR -flipC-> (aR,cR)bB
 | 
					
						
							|  |  |  | func (n *Node) flipColors() {
 | 
					
						
							|  |  |  | 	// Assumes: n has two children.
 | 
					
						
							|  |  |  | 	n.Color = !n.Color
 | 
					
						
							|  |  |  | 	n.Left.Color = !n.Left.Color
 | 
					
						
							|  |  |  | 	n.Right.Color = !n.Right.Color
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // fixUp ensures that black link balance is correct, that red nodes lean left,
 | 
					
						
							|  |  |  | // and that 4 nodes are split in the case of BU23 and properly balanced in TD234.
 | 
					
						
							|  |  |  | func (n *Node) fixUp() *Node {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Right.color() == red {
 | 
					
						
							|  |  |  | 		if mode == td234 && n.Right.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			n.Right = n.Right.rotateRight()
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		n = n.rotateLeft()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Left.color() == red && n.Left.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.rotateRight()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if mode == bu23 && n.Left.color() == red && n.Right.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n.flipColors()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) moveRedLeft() *Node {
 | 
					
						
							|  |  |  | 	n.flipColors()
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Right.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n.Right = n.Right.rotateRight()
 | 
					
						
							|  |  |  | 		n = n.rotateLeft()
 | 
					
						
							|  |  |  | 		n.flipColors()
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 		if mode == td234 && n.Right.Right.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			n.Right = n.Right.rotateLeft()
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) moveRedRight() *Node {
 | 
					
						
							|  |  |  | 	n.flipColors()
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Left.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.rotateRight()
 | 
					
						
							|  |  |  | 		n.flipColors()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Len returns the number of elements stored in the Tree.
 | 
					
						
							|  |  |  | func (t *Tree) Len() int {
 | 
					
						
							|  |  |  | 	return t.Count
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | // Search returns the first match of qname in the Tree.
 | 
					
						
							|  |  |  | func (t *Tree) Search(qname string) (*Elem, bool) {
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	if t.Root == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		return nil, false
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	n, res := t.Root.search(qname)
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	if n == nil {
 | 
					
						
							|  |  |  | 		return nil, res
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n.Elem, res
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | // search searches the tree for qname and type.
 | 
					
						
							|  |  |  | func (n *Node) search(qname string) (*Node, bool) {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	for n != nil {
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		switch c := Less(n.Elem, qname); {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		case c == 0:
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 			return n, true
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		case c < 0:
 | 
					
						
							|  |  |  | 			n = n.Left
 | 
					
						
							|  |  |  | 		default:
 | 
					
						
							|  |  |  | 			n = n.Right
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-10-08 15:22:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	return n, false
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // Insert inserts rr into the Tree at the first match found
 | 
					
						
							|  |  |  | // with e or when a nil node is reached.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) Insert(rr dns.RR) {
 | 
					
						
							|  |  |  | 	var d int
 | 
					
						
							|  |  |  | 	t.Root, d = t.Root.insert(rr)
 | 
					
						
							|  |  |  | 	t.Count += d
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	t.Root.Color = black
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | // insert inserts rr in to the tree.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (n *Node) insert(rr dns.RR) (root *Node, d int) {
 | 
					
						
							|  |  |  | 	if n == nil {
 | 
					
						
							|  |  |  | 		return &Node{Elem: newElem(rr)}, 1
 | 
					
						
							|  |  |  | 	} else if n.Elem == nil {
 | 
					
						
							|  |  |  | 		n.Elem = newElem(rr)
 | 
					
						
							|  |  |  | 		return n, 1
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if mode == td234 {
 | 
					
						
							|  |  |  | 		if n.Left.color() == red && n.Right.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			n.flipColors()
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	switch c := Less(n.Elem, rr.Header().Name); {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	case c == 0:
 | 
					
						
							|  |  |  | 		n.Elem.Insert(rr)
 | 
					
						
							|  |  |  | 	case c < 0:
 | 
					
						
							|  |  |  | 		n.Left, d = n.Left.insert(rr)
 | 
					
						
							|  |  |  | 	default:
 | 
					
						
							|  |  |  | 		n.Right, d = n.Right.insert(rr)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Right.color() == red && n.Left.color() == black {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.rotateLeft()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Left.color() == red && n.Left.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.rotateRight()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if mode == bu23 {
 | 
					
						
							|  |  |  | 		if n.Left.color() == red && n.Right.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			n.flipColors()
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	root = n
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // DeleteMin deletes the node with the minimum value in the tree.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) DeleteMin() {
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	var d int
 | 
					
						
							|  |  |  | 	t.Root, d = t.Root.deleteMin()
 | 
					
						
							|  |  |  | 	t.Count += d
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	t.Root.Color = black
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) deleteMin() (root *Node, d int) {
 | 
					
						
							|  |  |  | 	if n.Left == nil {
 | 
					
						
							|  |  |  | 		return nil, -1
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Left.color() == black && n.Left.Left.color() == black {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.moveRedLeft()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	n.Left, d = n.Left.deleteMin()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	root = n.fixUp()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // DeleteMax deletes the node with the maximum value in the tree.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) DeleteMax() {
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	var d int
 | 
					
						
							|  |  |  | 	t.Root, d = t.Root.deleteMax()
 | 
					
						
							|  |  |  | 	t.Count += d
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	t.Root.Color = black
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) deleteMax() (root *Node, d int) {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Left != nil && n.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.rotateRight()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if n.Right == nil {
 | 
					
						
							|  |  |  | 		return nil, -1
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	if n.Right.color() == black && n.Right.Left.color() == black {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		n = n.moveRedRight()
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	n.Right, d = n.Right.deleteMax()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	root = n.fixUp()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // Delete removes rr from the tree, is the node turns empty, that node is deleted with DeleteNode.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) Delete(rr dns.RR) {
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 16:56:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	el, _ := t.Search(rr.Header().Name)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if el == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		t.deleteNode(rr)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 16:56:16 +01:00
										 |  |  | 	// Delete from this element.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	empty := el.Delete(rr)
 | 
					
						
							|  |  |  | 	if empty {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		t.deleteNode(rr)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // DeleteNode deletes the node that matches rr according to Less().
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | func (t *Tree) deleteNode(rr dns.RR) {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	var d int
 | 
					
						
							|  |  |  | 	t.Root, d = t.Root.delete(rr)
 | 
					
						
							|  |  |  | 	t.Count += d
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 	t.Root.Color = black
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) delete(rr dns.RR) (root *Node, d int) {
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	if Less(n.Elem, rr.Header().Name) < 0 {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 		if n.Left != nil {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 			if n.Left.color() == black && n.Left.Left.color() == black {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 				n = n.moveRedLeft()
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			n.Left, d = n.Left.delete(rr)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	} else {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 		if n.Left.color() == red {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			n = n.rotateRight()
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		if n.Right == nil && Less(n.Elem, rr.Header().Name) == 0 {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			return nil, -1
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if n.Right != nil {
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | 			if n.Right.color() == black && n.Right.Left.color() == black {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 				n = n.moveRedRight()
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 			if Less(n.Elem, rr.Header().Name) == 0 {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 				n.Elem = n.Right.min().Elem
 | 
					
						
							|  |  |  | 				n.Right, d = n.Right.deleteMin()
 | 
					
						
							|  |  |  | 			} else {
 | 
					
						
							|  |  |  | 				n.Right, d = n.Right.delete(rr)
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	root = n.fixUp()
 | 
					
						
							|  |  |  | 	return
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // Min returns the minimum value stored in the tree.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) Min() *Elem {
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return t.Root.min().Elem
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) min() *Node {
 | 
					
						
							|  |  |  | 	for ; n.Left != nil; n = n.Left {
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:18:16 +01:00
										 |  |  | // Max returns the maximum value stored in the tree.
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | func (t *Tree) Max() *Elem {
 | 
					
						
							|  |  |  | 	if t.Root == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return t.Root.max().Elem
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (n *Node) max() *Node {
 | 
					
						
							|  |  |  | 	for ; n.Right != nil; n = n.Right {
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | // Prev returns the greatest value equal to or less than the qname according to Less().
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | func (t *Tree) Prev(qname string) (*Elem, bool) {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if t.Root == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		return nil, false
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	n := t.Root.floor(qname)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if n == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		return nil, false
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	return n.Elem, true
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | func (n *Node) floor(qname string) *Node {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if n == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	switch c := Less(n.Elem, qname); {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	case c == 0:
 | 
					
						
							|  |  |  | 		return n
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	case c <= 0:
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		return n.Left.floor(qname)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	default:
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		if r := n.Right.floor(qname); r != nil {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			return r
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | // Next returns the smallest value equal to or greater than the qname according to Less().
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | func (t *Tree) Next(qname string) (*Elem, bool) {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if t.Root == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		return nil, false
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	n := t.Root.ceil(qname)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if n == nil {
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		return nil, false
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	return n.Elem, true
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | func (n *Node) ceil(qname string) *Node {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	if n == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 	switch c := Less(n.Elem, qname); {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	case c == 0:
 | 
					
						
							|  |  |  | 		return n
 | 
					
						
							|  |  |  | 	case c > 0:
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		return n.Right.ceil(qname)
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	default:
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:49:13 +01:00
										 |  |  | 		if l := n.Left.ceil(qname); l != nil {
 | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 			return l
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return n
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | Copyright ©2012 The bíogo Authors. All rights reserved.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Redistribution and use in source and binary forms, with or without
 | 
					
						
							|  |  |  | modification, are permitted provided that the following conditions are met:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * Redistributions of source code must retain the above copyright
 | 
					
						
							|  |  |  |   notice, this list of conditions and the following disclaimer.
 | 
					
						
							|  |  |  | * Redistributions in binary form must reproduce the above copyright
 | 
					
						
							|  |  |  |   notice, this list of conditions and the following disclaimer in the
 | 
					
						
							|  |  |  |   documentation and/or other materials provided with the distribution.
 | 
					
						
							|  |  |  | * Neither the name of the bíogo project nor the names of its authors and
 | 
					
						
							|  |  |  |   contributors may be used to endorse or promote products derived from this
 | 
					
						
							|  |  |  |   software without specific prior written permission.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
					
						
							|  |  |  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
					
						
							|  |  |  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
					
						
							|  |  |  | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | 
					
						
							|  |  |  | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
					
						
							|  |  |  | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
					
						
							|  |  |  | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
					
						
							|  |  |  | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
					
						
							|  |  |  | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					
						
							|  |  |  | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					
						
							|  |  |  | */
 |