mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	Update kubernetes/client-go to v7.0.0 (#1808)
This fix updates k8s' client-go to v7.0.0, which matches k8s 1.10. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
		
							
								
								
									
										23
									
								
								vendor/github.com/petar/GoLLRB/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/petar/GoLLRB/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,23 +0,0 @@ | ||||
| syntax:glob | ||||
| *.[568ao] | ||||
| *.ao | ||||
| *.so | ||||
| *.pyc | ||||
| *.swp | ||||
| *.swo | ||||
| ._* | ||||
| .nfs.* | ||||
| [568a].out | ||||
| *~ | ||||
| *.orig | ||||
| *.pb.go | ||||
| core | ||||
| _obj | ||||
| _test | ||||
| src/pkg/Make.deps | ||||
| _testmain.go | ||||
|  | ||||
| syntax:regexp | ||||
| ^pkg/ | ||||
| ^src/cmd/(.*)/6?\1$ | ||||
| ^.*/core.[0-9]*$ | ||||
							
								
								
									
										4
									
								
								vendor/github.com/petar/GoLLRB/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/petar/GoLLRB/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| Petar Maymounkov <petar@5ttt.org> | ||||
| Vadim Vygonets <vadik@vygo.net> | ||||
| Ian Smith <iansmith@acm.org> | ||||
| Martin Bruse | ||||
							
								
								
									
										27
									
								
								vendor/github.com/petar/GoLLRB/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/petar/GoLLRB/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| Copyright (c) 2010, Petar Maymounkov | ||||
| 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 Petar Maymounkov nor the names of its 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. | ||||
							
								
								
									
										66
									
								
								vendor/github.com/petar/GoLLRB/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/petar/GoLLRB/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,66 +0,0 @@ | ||||
| # GoLLRB | ||||
|  | ||||
| GoLLRB is a Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary | ||||
| search trees in Go Language. | ||||
|  | ||||
| ## Overview | ||||
|  | ||||
| As of this writing and to the best of the author's knowledge,  | ||||
| Go still does not have a balanced binary search tree (BBST) data structure. | ||||
| These data structures are quite useful in a variety of cases. A BBST maintains | ||||
| elements in sorted order under dynamic updates (inserts and deletes) and can | ||||
| support various order-specific queries. Furthermore, in practice one often | ||||
| implements other common data structures like Priority Queues, using BBST's. | ||||
|  | ||||
| 2-3 trees (a type of BBST's), as well as the runtime-similar 2-3-4 trees, are | ||||
| the de facto standard BBST algoritms found in implementations of Python, Java, | ||||
| and other libraries. The LLRB method of implementing 2-3 trees is a recent | ||||
| improvement over the traditional implementation. The LLRB approach was | ||||
| discovered relatively recently (in 2008) by Robert Sedgewick of Princeton | ||||
| University. | ||||
|  | ||||
| GoLLRB is a Go implementation of LLRB 2-3 trees. | ||||
|  | ||||
| ## Maturity | ||||
|  | ||||
| GoLLRB has been used in some pretty heavy-weight machine learning tasks over many gigabytes of data. | ||||
| I consider it to be in stable, perhaps even production, shape. There are no known bugs. | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| With a healthy Go Language installed, simply run `go get github.com/petar/GoLLRB/llrb` | ||||
|  | ||||
| ## Example | ||||
|      | ||||
| 	package main | ||||
|  | ||||
| 	import ( | ||||
| 		"fmt" | ||||
| 		"github.com/petar/GoLLRB/llrb" | ||||
| 	) | ||||
|  | ||||
| 	func lessInt(a, b interface{}) bool { return a.(int) < b.(int) } | ||||
|  | ||||
| 	func main() { | ||||
| 		tree := llrb.New(lessInt) | ||||
| 		tree.ReplaceOrInsert(1) | ||||
| 		tree.ReplaceOrInsert(2) | ||||
| 		tree.ReplaceOrInsert(3) | ||||
| 		tree.ReplaceOrInsert(4) | ||||
| 		tree.DeleteMin() | ||||
| 		tree.Delete(4) | ||||
| 		c := tree.IterAscend() | ||||
| 		for { | ||||
| 			u := <-c | ||||
| 			if u == nil { | ||||
| 				break | ||||
| 			} | ||||
| 			fmt.Printf("%d\n", int(u.(int))) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| ## About | ||||
|  | ||||
| GoLLRB was written by [Petar Maymounkov](http://pdos.csail.mit.edu/~petar/).  | ||||
|  | ||||
| Follow me on [Twitter @maymounkov](http://www.twitter.com/maymounkov)! | ||||
							
								
								
									
										39
									
								
								vendor/github.com/petar/GoLLRB/llrb/avgvar.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/petar/GoLLRB/llrb/avgvar.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,39 +0,0 @@ | ||||
| // Copyright 2010 Petar Maymounkov. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package llrb | ||||
|  | ||||
| import "math" | ||||
|  | ||||
| // avgVar maintains the average and variance of a stream of numbers | ||||
| // in a space-efficient manner. | ||||
| type avgVar struct { | ||||
| 	count      int64 | ||||
| 	sum, sumsq float64 | ||||
| } | ||||
|  | ||||
| func (av *avgVar) Init() { | ||||
| 	av.count = 0 | ||||
| 	av.sum = 0.0 | ||||
| 	av.sumsq = 0.0 | ||||
| } | ||||
|  | ||||
| func (av *avgVar) Add(sample float64) { | ||||
| 	av.count++ | ||||
| 	av.sum += sample | ||||
| 	av.sumsq += sample * sample | ||||
| } | ||||
|  | ||||
| func (av *avgVar) GetCount() int64 { return av.count } | ||||
|  | ||||
| func (av *avgVar) GetAvg() float64 { return av.sum / float64(av.count) } | ||||
|  | ||||
| func (av *avgVar) GetTotal() float64 { return av.sum } | ||||
|  | ||||
| func (av *avgVar) GetVar() float64 { | ||||
| 	a := av.GetAvg() | ||||
| 	return av.sumsq/float64(av.count) - a*a | ||||
| } | ||||
|  | ||||
| func (av *avgVar) GetStdDev() float64 { return math.Sqrt(av.GetVar()) } | ||||
							
								
								
									
										93
									
								
								vendor/github.com/petar/GoLLRB/llrb/iterator.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										93
									
								
								vendor/github.com/petar/GoLLRB/llrb/iterator.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,93 +0,0 @@ | ||||
| package llrb | ||||
|  | ||||
| type ItemIterator func(i Item) bool | ||||
|  | ||||
| //func (t *Tree) Ascend(iterator ItemIterator) { | ||||
| //	t.AscendGreaterOrEqual(Inf(-1), iterator) | ||||
| //} | ||||
|  | ||||
| func (t *LLRB) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) { | ||||
| 	t.ascendRange(t.root, greaterOrEqual, lessThan, iterator) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) ascendRange(h *Node, inf, sup Item, iterator ItemIterator) bool { | ||||
| 	if h == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if !less(h.Item, sup) { | ||||
| 		return t.ascendRange(h.Left, inf, sup, iterator) | ||||
| 	} | ||||
| 	if less(h.Item, inf) { | ||||
| 		return t.ascendRange(h.Right, inf, sup, iterator) | ||||
| 	} | ||||
|  | ||||
| 	if !t.ascendRange(h.Left, inf, sup, iterator) { | ||||
| 		return false | ||||
| 	} | ||||
| 	if !iterator(h.Item) { | ||||
| 		return false | ||||
| 	} | ||||
| 	return t.ascendRange(h.Right, inf, sup, iterator) | ||||
| } | ||||
|  | ||||
| // AscendGreaterOrEqual will call iterator once for each element greater or equal to | ||||
| // pivot in ascending order. It will stop whenever the iterator returns false. | ||||
| func (t *LLRB) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) { | ||||
| 	t.ascendGreaterOrEqual(t.root, pivot, iterator) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) ascendGreaterOrEqual(h *Node, pivot Item, iterator ItemIterator) bool { | ||||
| 	if h == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if !less(h.Item, pivot) { | ||||
| 		if !t.ascendGreaterOrEqual(h.Left, pivot, iterator) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if !iterator(h.Item) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return t.ascendGreaterOrEqual(h.Right, pivot, iterator) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) AscendLessThan(pivot Item, iterator ItemIterator) { | ||||
| 	t.ascendLessThan(t.root, pivot, iterator) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) ascendLessThan(h *Node, pivot Item, iterator ItemIterator) bool { | ||||
| 	if h == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if !t.ascendLessThan(h.Left, pivot, iterator) { | ||||
| 		return false | ||||
| 	} | ||||
| 	if !iterator(h.Item) { | ||||
| 		return false | ||||
| 	} | ||||
| 	if less(h.Item, pivot) { | ||||
| 		return t.ascendLessThan(h.Left, pivot, iterator) | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // DescendLessOrEqual will call iterator once for each element less than the | ||||
| // pivot in descending order. It will stop whenever the iterator returns false. | ||||
| func (t *LLRB) DescendLessOrEqual(pivot Item, iterator ItemIterator) { | ||||
| 	t.descendLessOrEqual(t.root, pivot, iterator) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) descendLessOrEqual(h *Node, pivot Item, iterator ItemIterator) bool { | ||||
| 	if h == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if less(h.Item, pivot) || !less(pivot, h.Item) { | ||||
| 		if !t.descendLessOrEqual(h.Right, pivot, iterator) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if !iterator(h.Item) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return t.descendLessOrEqual(h.Left, pivot, iterator) | ||||
| } | ||||
							
								
								
									
										76
									
								
								vendor/github.com/petar/GoLLRB/llrb/iterator_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/petar/GoLLRB/llrb/iterator_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,76 +0,0 @@ | ||||
| package llrb | ||||
|  | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestAscendGreaterOrEqual(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	tree.InsertNoReplace(Int(4)) | ||||
| 	tree.InsertNoReplace(Int(6)) | ||||
| 	tree.InsertNoReplace(Int(1)) | ||||
| 	tree.InsertNoReplace(Int(3)) | ||||
| 	var ary []Item | ||||
| 	tree.AscendGreaterOrEqual(Int(-1), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected := []Item{Int(1), Int(3), Int(4), Int(6)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| 	ary = nil | ||||
| 	tree.AscendGreaterOrEqual(Int(3), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected = []Item{Int(3), Int(4), Int(6)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| 	ary = nil | ||||
| 	tree.AscendGreaterOrEqual(Int(2), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected = []Item{Int(3), Int(4), Int(6)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestDescendLessOrEqual(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	tree.InsertNoReplace(Int(4)) | ||||
| 	tree.InsertNoReplace(Int(6)) | ||||
| 	tree.InsertNoReplace(Int(1)) | ||||
| 	tree.InsertNoReplace(Int(3)) | ||||
| 	var ary []Item | ||||
| 	tree.DescendLessOrEqual(Int(10), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected := []Item{Int(6), Int(4), Int(3), Int(1)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| 	ary = nil | ||||
| 	tree.DescendLessOrEqual(Int(4), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected = []Item{Int(4), Int(3), Int(1)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| 	ary = nil | ||||
| 	tree.DescendLessOrEqual(Int(5), func(i Item) bool { | ||||
| 		ary = append(ary, i) | ||||
| 		return true | ||||
| 	}) | ||||
| 	expected = []Item{Int(4), Int(3), Int(1)} | ||||
| 	if !reflect.DeepEqual(ary, expected) { | ||||
| 		t.Errorf("expected %v but got %v", expected, ary) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										46
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,46 +0,0 @@ | ||||
| // Copyright 2010 Petar Maymounkov. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package llrb | ||||
|  | ||||
| // GetHeight() returns an item in the tree with key @key, and it's height in the tree | ||||
| func (t *LLRB) GetHeight(key Item) (result Item, depth int) { | ||||
| 	return t.getHeight(t.root, key) | ||||
| } | ||||
|  | ||||
| func (t *LLRB) getHeight(h *Node, item Item) (Item, int) { | ||||
| 	if h == nil { | ||||
| 		return nil, 0 | ||||
| 	} | ||||
| 	if less(item, h.Item) { | ||||
| 		result, depth := t.getHeight(h.Left, item) | ||||
| 		return result, depth + 1 | ||||
| 	} | ||||
| 	if less(h.Item, item) { | ||||
| 		result, depth := t.getHeight(h.Right, item) | ||||
| 		return result, depth + 1 | ||||
| 	} | ||||
| 	return h.Item, 0 | ||||
| } | ||||
|  | ||||
| // HeightStats() returns the average and standard deviation of the height | ||||
| // of elements in the tree | ||||
| func (t *LLRB) HeightStats() (avg, stddev float64) { | ||||
| 	av := &avgVar{} | ||||
| 	heightStats(t.root, 0, av) | ||||
| 	return av.GetAvg(), av.GetStdDev() | ||||
| } | ||||
|  | ||||
| func heightStats(h *Node, d int, av *avgVar) { | ||||
| 	if h == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	av.Add(float64(d)) | ||||
| 	if h.Left != nil { | ||||
| 		heightStats(h.Left, d+1, av) | ||||
| 	} | ||||
| 	if h.Right != nil { | ||||
| 		heightStats(h.Right, d+1, av) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										456
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										456
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,456 +0,0 @@ | ||||
| // Copyright 2010 Petar Maymounkov. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees, | ||||
| // based on the following work: | ||||
| // | ||||
| //   http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf | ||||
| //   http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf | ||||
| //   http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java | ||||
| // | ||||
| //  2-3 trees (and the run-time equivalent 2-3-4 trees) are the de facto standard BST | ||||
| //  algoritms found in implementations of Python, Java, and other libraries. The LLRB | ||||
| //  implementation of 2-3 trees is a recent improvement on the traditional implementation, | ||||
| //  observed and documented by Robert Sedgewick. | ||||
| // | ||||
| package llrb | ||||
|  | ||||
| // Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees | ||||
| type LLRB struct { | ||||
| 	count int | ||||
| 	root  *Node | ||||
| } | ||||
|  | ||||
| type Node struct { | ||||
| 	Item | ||||
| 	Left, Right *Node // Pointers to left and right child nodes | ||||
| 	Black       bool  // If set, the color of the link (incoming from the parent) is black | ||||
| 	// In the LLRB, new nodes are always red, hence the zero-value for node | ||||
| } | ||||
|  | ||||
| type Item interface { | ||||
| 	Less(than Item) bool | ||||
| } | ||||
|  | ||||
| // | ||||
| func less(x, y Item) bool { | ||||
| 	if x == pinf { | ||||
| 		return false | ||||
| 	} | ||||
| 	if x == ninf { | ||||
| 		return true | ||||
| 	} | ||||
| 	return x.Less(y) | ||||
| } | ||||
|  | ||||
| // Inf returns an Item that is "bigger than" any other item, if sign is positive. | ||||
| // Otherwise  it returns an Item that is "smaller than" any other item. | ||||
| func Inf(sign int) Item { | ||||
| 	if sign == 0 { | ||||
| 		panic("sign") | ||||
| 	} | ||||
| 	if sign > 0 { | ||||
| 		return pinf | ||||
| 	} | ||||
| 	return ninf | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	ninf = nInf{} | ||||
| 	pinf = pInf{} | ||||
| ) | ||||
|  | ||||
| type nInf struct{} | ||||
|  | ||||
| func (nInf) Less(Item) bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| type pInf struct{} | ||||
|  | ||||
| func (pInf) Less(Item) bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // New() allocates a new tree | ||||
| func New() *LLRB { | ||||
| 	return &LLRB{} | ||||
| } | ||||
|  | ||||
| // SetRoot sets the root node of the tree. | ||||
| // It is intended to be used by functions that deserialize the tree. | ||||
| func (t *LLRB) SetRoot(r *Node) { | ||||
| 	t.root = r | ||||
| } | ||||
|  | ||||
| // Root returns the root node of the tree. | ||||
| // It is intended to be used by functions that serialize the tree. | ||||
| func (t *LLRB) Root() *Node { | ||||
| 	return t.root | ||||
| } | ||||
|  | ||||
| // Len returns the number of nodes in the tree. | ||||
| func (t *LLRB) Len() int { return t.count } | ||||
|  | ||||
| // Has returns true if the tree contains an element whose order is the same as that of key. | ||||
| func (t *LLRB) Has(key Item) bool { | ||||
| 	return t.Get(key) != nil | ||||
| } | ||||
|  | ||||
| // Get retrieves an element from the tree whose order is the same as that of key. | ||||
| func (t *LLRB) Get(key Item) Item { | ||||
| 	h := t.root | ||||
| 	for h != nil { | ||||
| 		switch { | ||||
| 		case less(key, h.Item): | ||||
| 			h = h.Left | ||||
| 		case less(h.Item, key): | ||||
| 			h = h.Right | ||||
| 		default: | ||||
| 			return h.Item | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Min returns the minimum element in the tree. | ||||
| func (t *LLRB) Min() Item { | ||||
| 	h := t.root | ||||
| 	if h == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	for h.Left != nil { | ||||
| 		h = h.Left | ||||
| 	} | ||||
| 	return h.Item | ||||
| } | ||||
|  | ||||
| // Max returns the maximum element in the tree. | ||||
| func (t *LLRB) Max() Item { | ||||
| 	h := t.root | ||||
| 	if h == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	for h.Right != nil { | ||||
| 		h = h.Right | ||||
| 	} | ||||
| 	return h.Item | ||||
| } | ||||
|  | ||||
| func (t *LLRB) ReplaceOrInsertBulk(items ...Item) { | ||||
| 	for _, i := range items { | ||||
| 		t.ReplaceOrInsert(i) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (t *LLRB) InsertNoReplaceBulk(items ...Item) { | ||||
| 	for _, i := range items { | ||||
| 		t.InsertNoReplace(i) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReplaceOrInsert inserts item into the tree. If an existing | ||||
| // element has the same order, it is removed from the tree and returned. | ||||
| func (t *LLRB) ReplaceOrInsert(item Item) Item { | ||||
| 	if item == nil { | ||||
| 		panic("inserting nil item") | ||||
| 	} | ||||
| 	var replaced Item | ||||
| 	t.root, replaced = t.replaceOrInsert(t.root, item) | ||||
| 	t.root.Black = true | ||||
| 	if replaced == nil { | ||||
| 		t.count++ | ||||
| 	} | ||||
| 	return replaced | ||||
| } | ||||
|  | ||||
| func (t *LLRB) replaceOrInsert(h *Node, item Item) (*Node, Item) { | ||||
| 	if h == nil { | ||||
| 		return newNode(item), nil | ||||
| 	} | ||||
|  | ||||
| 	h = walkDownRot23(h) | ||||
|  | ||||
| 	var replaced Item | ||||
| 	if less(item, h.Item) { // BUG | ||||
| 		h.Left, replaced = t.replaceOrInsert(h.Left, item) | ||||
| 	} else if less(h.Item, item) { | ||||
| 		h.Right, replaced = t.replaceOrInsert(h.Right, item) | ||||
| 	} else { | ||||
| 		replaced, h.Item = h.Item, item | ||||
| 	} | ||||
|  | ||||
| 	h = walkUpRot23(h) | ||||
|  | ||||
| 	return h, replaced | ||||
| } | ||||
|  | ||||
| // InsertNoReplace inserts item into the tree. If an existing | ||||
| // element has the same order, both elements remain in the tree. | ||||
| func (t *LLRB) InsertNoReplace(item Item) { | ||||
| 	if item == nil { | ||||
| 		panic("inserting nil item") | ||||
| 	} | ||||
| 	t.root = t.insertNoReplace(t.root, item) | ||||
| 	t.root.Black = true | ||||
| 	t.count++ | ||||
| } | ||||
|  | ||||
| func (t *LLRB) insertNoReplace(h *Node, item Item) *Node { | ||||
| 	if h == nil { | ||||
| 		return newNode(item) | ||||
| 	} | ||||
|  | ||||
| 	h = walkDownRot23(h) | ||||
|  | ||||
| 	if less(item, h.Item) { | ||||
| 		h.Left = t.insertNoReplace(h.Left, item) | ||||
| 	} else { | ||||
| 		h.Right = t.insertNoReplace(h.Right, item) | ||||
| 	} | ||||
|  | ||||
| 	return walkUpRot23(h) | ||||
| } | ||||
|  | ||||
| // Rotation driver routines for 2-3 algorithm | ||||
|  | ||||
| func walkDownRot23(h *Node) *Node { return h } | ||||
|  | ||||
| func walkUpRot23(h *Node) *Node { | ||||
| 	if isRed(h.Right) && !isRed(h.Left) { | ||||
| 		h = rotateLeft(h) | ||||
| 	} | ||||
|  | ||||
| 	if isRed(h.Left) && isRed(h.Left.Left) { | ||||
| 		h = rotateRight(h) | ||||
| 	} | ||||
|  | ||||
| 	if isRed(h.Left) && isRed(h.Right) { | ||||
| 		flip(h) | ||||
| 	} | ||||
|  | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| // Rotation driver routines for 2-3-4 algorithm | ||||
|  | ||||
| func walkDownRot234(h *Node) *Node { | ||||
| 	if isRed(h.Left) && isRed(h.Right) { | ||||
| 		flip(h) | ||||
| 	} | ||||
|  | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| func walkUpRot234(h *Node) *Node { | ||||
| 	if isRed(h.Right) && !isRed(h.Left) { | ||||
| 		h = rotateLeft(h) | ||||
| 	} | ||||
|  | ||||
| 	if isRed(h.Left) && isRed(h.Left.Left) { | ||||
| 		h = rotateRight(h) | ||||
| 	} | ||||
|  | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| // DeleteMin deletes the minimum element in the tree and returns the | ||||
| // deleted item or nil otherwise. | ||||
| func (t *LLRB) DeleteMin() Item { | ||||
| 	var deleted Item | ||||
| 	t.root, deleted = deleteMin(t.root) | ||||
| 	if t.root != nil { | ||||
| 		t.root.Black = true | ||||
| 	} | ||||
| 	if deleted != nil { | ||||
| 		t.count-- | ||||
| 	} | ||||
| 	return deleted | ||||
| } | ||||
|  | ||||
| // deleteMin code for LLRB 2-3 trees | ||||
| func deleteMin(h *Node) (*Node, Item) { | ||||
| 	if h == nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	if h.Left == nil { | ||||
| 		return nil, h.Item | ||||
| 	} | ||||
|  | ||||
| 	if !isRed(h.Left) && !isRed(h.Left.Left) { | ||||
| 		h = moveRedLeft(h) | ||||
| 	} | ||||
|  | ||||
| 	var deleted Item | ||||
| 	h.Left, deleted = deleteMin(h.Left) | ||||
|  | ||||
| 	return fixUp(h), deleted | ||||
| } | ||||
|  | ||||
| // DeleteMax deletes the maximum element in the tree and returns | ||||
| // the deleted item or nil otherwise | ||||
| func (t *LLRB) DeleteMax() Item { | ||||
| 	var deleted Item | ||||
| 	t.root, deleted = deleteMax(t.root) | ||||
| 	if t.root != nil { | ||||
| 		t.root.Black = true | ||||
| 	} | ||||
| 	if deleted != nil { | ||||
| 		t.count-- | ||||
| 	} | ||||
| 	return deleted | ||||
| } | ||||
|  | ||||
| func deleteMax(h *Node) (*Node, Item) { | ||||
| 	if h == nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	if isRed(h.Left) { | ||||
| 		h = rotateRight(h) | ||||
| 	} | ||||
| 	if h.Right == nil { | ||||
| 		return nil, h.Item | ||||
| 	} | ||||
| 	if !isRed(h.Right) && !isRed(h.Right.Left) { | ||||
| 		h = moveRedRight(h) | ||||
| 	} | ||||
| 	var deleted Item | ||||
| 	h.Right, deleted = deleteMax(h.Right) | ||||
|  | ||||
| 	return fixUp(h), deleted | ||||
| } | ||||
|  | ||||
| // Delete deletes an item from the tree whose key equals key. | ||||
| // The deleted item is return, otherwise nil is returned. | ||||
| func (t *LLRB) Delete(key Item) Item { | ||||
| 	var deleted Item | ||||
| 	t.root, deleted = t.delete(t.root, key) | ||||
| 	if t.root != nil { | ||||
| 		t.root.Black = true | ||||
| 	} | ||||
| 	if deleted != nil { | ||||
| 		t.count-- | ||||
| 	} | ||||
| 	return deleted | ||||
| } | ||||
|  | ||||
| func (t *LLRB) delete(h *Node, item Item) (*Node, Item) { | ||||
| 	var deleted Item | ||||
| 	if h == nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	if less(item, h.Item) { | ||||
| 		if h.Left == nil { // item not present. Nothing to delete | ||||
| 			return h, nil | ||||
| 		} | ||||
| 		if !isRed(h.Left) && !isRed(h.Left.Left) { | ||||
| 			h = moveRedLeft(h) | ||||
| 		} | ||||
| 		h.Left, deleted = t.delete(h.Left, item) | ||||
| 	} else { | ||||
| 		if isRed(h.Left) { | ||||
| 			h = rotateRight(h) | ||||
| 		} | ||||
| 		// If @item equals @h.Item and no right children at @h | ||||
| 		if !less(h.Item, item) && h.Right == nil { | ||||
| 			return nil, h.Item | ||||
| 		} | ||||
| 		// PETAR: Added 'h.Right != nil' below | ||||
| 		if h.Right != nil && !isRed(h.Right) && !isRed(h.Right.Left) { | ||||
| 			h = moveRedRight(h) | ||||
| 		} | ||||
| 		// If @item equals @h.Item, and (from above) 'h.Right != nil' | ||||
| 		if !less(h.Item, item) { | ||||
| 			var subDeleted Item | ||||
| 			h.Right, subDeleted = deleteMin(h.Right) | ||||
| 			if subDeleted == nil { | ||||
| 				panic("logic") | ||||
| 			} | ||||
| 			deleted, h.Item = h.Item, subDeleted | ||||
| 		} else { // Else, @item is bigger than @h.Item | ||||
| 			h.Right, deleted = t.delete(h.Right, item) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return fixUp(h), deleted | ||||
| } | ||||
|  | ||||
| // Internal node manipulation routines | ||||
|  | ||||
| func newNode(item Item) *Node { return &Node{Item: item} } | ||||
|  | ||||
| func isRed(h *Node) bool { | ||||
| 	if h == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return !h.Black | ||||
| } | ||||
|  | ||||
| func rotateLeft(h *Node) *Node { | ||||
| 	x := h.Right | ||||
| 	if x.Black { | ||||
| 		panic("rotating a black link") | ||||
| 	} | ||||
| 	h.Right = x.Left | ||||
| 	x.Left = h | ||||
| 	x.Black = h.Black | ||||
| 	h.Black = false | ||||
| 	return x | ||||
| } | ||||
|  | ||||
| func rotateRight(h *Node) *Node { | ||||
| 	x := h.Left | ||||
| 	if x.Black { | ||||
| 		panic("rotating a black link") | ||||
| 	} | ||||
| 	h.Left = x.Right | ||||
| 	x.Right = h | ||||
| 	x.Black = h.Black | ||||
| 	h.Black = false | ||||
| 	return x | ||||
| } | ||||
|  | ||||
| // REQUIRE: Left and Right children must be present | ||||
| func flip(h *Node) { | ||||
| 	h.Black = !h.Black | ||||
| 	h.Left.Black = !h.Left.Black | ||||
| 	h.Right.Black = !h.Right.Black | ||||
| } | ||||
|  | ||||
| // REQUIRE: Left and Right children must be present | ||||
| func moveRedLeft(h *Node) *Node { | ||||
| 	flip(h) | ||||
| 	if isRed(h.Right.Left) { | ||||
| 		h.Right = rotateRight(h.Right) | ||||
| 		h = rotateLeft(h) | ||||
| 		flip(h) | ||||
| 	} | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| // REQUIRE: Left and Right children must be present | ||||
| func moveRedRight(h *Node) *Node { | ||||
| 	flip(h) | ||||
| 	if isRed(h.Left.Left) { | ||||
| 		h = rotateRight(h) | ||||
| 		flip(h) | ||||
| 	} | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| func fixUp(h *Node) *Node { | ||||
| 	if isRed(h.Right) { | ||||
| 		h = rotateLeft(h) | ||||
| 	} | ||||
|  | ||||
| 	if isRed(h.Left) && isRed(h.Left.Left) { | ||||
| 		h = rotateRight(h) | ||||
| 	} | ||||
|  | ||||
| 	if isRed(h.Left) && isRed(h.Right) { | ||||
| 		flip(h) | ||||
| 	} | ||||
|  | ||||
| 	return h | ||||
| } | ||||
							
								
								
									
										239
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										239
									
								
								vendor/github.com/petar/GoLLRB/llrb/llrb_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,239 +0,0 @@ | ||||
| // Copyright 2010 Petar Maymounkov. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package llrb | ||||
|  | ||||
| import ( | ||||
| 	"math" | ||||
| 	"math/rand" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestCases(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	tree.ReplaceOrInsert(Int(1)) | ||||
| 	tree.ReplaceOrInsert(Int(1)) | ||||
| 	if tree.Len() != 1 { | ||||
| 		t.Errorf("expecting len 1") | ||||
| 	} | ||||
| 	if !tree.Has(Int(1)) { | ||||
| 		t.Errorf("expecting to find key=1") | ||||
| 	} | ||||
|  | ||||
| 	tree.Delete(Int(1)) | ||||
| 	if tree.Len() != 0 { | ||||
| 		t.Errorf("expecting len 0") | ||||
| 	} | ||||
| 	if tree.Has(Int(1)) { | ||||
| 		t.Errorf("not expecting to find key=1") | ||||
| 	} | ||||
|  | ||||
| 	tree.Delete(Int(1)) | ||||
| 	if tree.Len() != 0 { | ||||
| 		t.Errorf("expecting len 0") | ||||
| 	} | ||||
| 	if tree.Has(Int(1)) { | ||||
| 		t.Errorf("not expecting to find key=1") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestReverseInsertOrder(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 100 | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(n - i)) | ||||
| 	} | ||||
| 	i := 0 | ||||
| 	tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { | ||||
| 		i++ | ||||
| 		if item.(Int) != Int(i) { | ||||
| 			t.Errorf("bad order: got %d, expect %d", item.(Int), i) | ||||
| 		} | ||||
| 		return true | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRange(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	order := []String{ | ||||
| 		"ab", "aba", "abc", "a", "aa", "aaa", "b", "a-", "a!", | ||||
| 	} | ||||
| 	for _, i := range order { | ||||
| 		tree.ReplaceOrInsert(i) | ||||
| 	} | ||||
| 	k := 0 | ||||
| 	tree.AscendRange(String("ab"), String("ac"), func(item Item) bool { | ||||
| 		if k > 3 { | ||||
| 			t.Fatalf("returned more items than expected") | ||||
| 		} | ||||
| 		i1 := order[k] | ||||
| 		i2 := item.(String) | ||||
| 		if i1 != i2 { | ||||
| 			t.Errorf("expecting %s, got %s", i1, i2) | ||||
| 		} | ||||
| 		k++ | ||||
| 		return true | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRandomInsertOrder(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 1000 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	j := 0 | ||||
| 	tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { | ||||
| 		if item.(Int) != Int(j) { | ||||
| 			t.Fatalf("bad order") | ||||
| 		} | ||||
| 		j++ | ||||
| 		return true | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRandomReplace(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 100 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	perm = rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		if replaced := tree.ReplaceOrInsert(Int(perm[i])); replaced == nil || replaced.(Int) != Int(perm[i]) { | ||||
| 			t.Errorf("error replacing") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestRandomInsertSequentialDelete(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 1000 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.Delete(Int(i)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestRandomInsertDeleteNonExistent(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 100 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	if tree.Delete(Int(200)) != nil { | ||||
| 		t.Errorf("deleted non-existent item") | ||||
| 	} | ||||
| 	if tree.Delete(Int(-2)) != nil { | ||||
| 		t.Errorf("deleted non-existent item") | ||||
| 	} | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		if u := tree.Delete(Int(i)); u == nil || u.(Int) != Int(i) { | ||||
| 			t.Errorf("delete failed") | ||||
| 		} | ||||
| 	} | ||||
| 	if tree.Delete(Int(200)) != nil { | ||||
| 		t.Errorf("deleted non-existent item") | ||||
| 	} | ||||
| 	if tree.Delete(Int(-2)) != nil { | ||||
| 		t.Errorf("deleted non-existent item") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestRandomInsertPartialDeleteOrder(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 100 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	for i := 1; i < n-1; i++ { | ||||
| 		tree.Delete(Int(i)) | ||||
| 	} | ||||
| 	j := 0 | ||||
| 	tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { | ||||
| 		switch j { | ||||
| 		case 0: | ||||
| 			if item.(Int) != Int(0) { | ||||
| 				t.Errorf("expecting 0") | ||||
| 			} | ||||
| 		case 1: | ||||
| 			if item.(Int) != Int(n-1) { | ||||
| 				t.Errorf("expecting %d", n-1) | ||||
| 			} | ||||
| 		} | ||||
| 		j++ | ||||
| 		return true | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRandomInsertStats(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 100000 | ||||
| 	perm := rand.Perm(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(perm[i])) | ||||
| 	} | ||||
| 	avg, _ := tree.HeightStats() | ||||
| 	expAvg := math.Log2(float64(n)) - 1.5 | ||||
| 	if math.Abs(avg-expAvg) >= 2.0 { | ||||
| 		t.Errorf("too much deviation from expected average height") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkInsert(b *testing.B) { | ||||
| 	tree := New() | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(b.N - i)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkDelete(b *testing.B) { | ||||
| 	b.StopTimer() | ||||
| 	tree := New() | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(b.N - i)) | ||||
| 	} | ||||
| 	b.StartTimer() | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		tree.Delete(Int(i)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkDeleteMin(b *testing.B) { | ||||
| 	b.StopTimer() | ||||
| 	tree := New() | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		tree.ReplaceOrInsert(Int(b.N - i)) | ||||
| 	} | ||||
| 	b.StartTimer() | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		tree.DeleteMin() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestInsertNoReplace(t *testing.T) { | ||||
| 	tree := New() | ||||
| 	n := 1000 | ||||
| 	for q := 0; q < 2; q++ { | ||||
| 		perm := rand.Perm(n) | ||||
| 		for i := 0; i < n; i++ { | ||||
| 			tree.InsertNoReplace(Int(perm[i])) | ||||
| 		} | ||||
| 	} | ||||
| 	j := 0 | ||||
| 	tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { | ||||
| 		if item.(Int) != Int(j/2) { | ||||
| 			t.Fatalf("bad order") | ||||
| 		} | ||||
| 		j++ | ||||
| 		return true | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/petar/GoLLRB/llrb/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/petar/GoLLRB/llrb/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| // Copyright 2010 Petar Maymounkov. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package llrb | ||||
|  | ||||
| type Int int | ||||
|  | ||||
| func (x Int) Less(than Item) bool { | ||||
| 	return x < than.(Int) | ||||
| } | ||||
|  | ||||
| type String string | ||||
|  | ||||
| func (x String) Less(than Item) bool { | ||||
| 	return x < than.(String) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user