mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 22:19:58 +00:00
TUN-528: Move cloudflared into a separate repo
This commit is contained in:
20
vendor/github.com/golang-collections/collections/LICENSE
generated
vendored
Normal file
20
vendor/github.com/golang-collections/collections/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2012 Caleb Doxsey
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
vendor/github.com/golang-collections/collections/Readme.md
generated
vendored
Normal file
26
vendor/github.com/golang-collections/collections/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Badgerodon Collections
|
||||
|
||||
Maps and slices go a long way in Go, but sometimes you need more. This is a collection of collections that may be useful.
|
||||
|
||||
## Queue
|
||||
A [queue](http://en.wikipedia.org/wiki/Queue_(data_structure%29) is a first-in first-out data structure.
|
||||
|
||||
## Set
|
||||
A [set](http://en.wikipedia.org/wiki/Set_(computer_science%29) is an unordered collection of unique values typically used for testing membership.
|
||||
|
||||
## Skip list
|
||||
A [skip list](http://en.wikipedia.org/wiki/Skip_list) is a data structure that stores nodes in a hierarchy of linked lists. It gives performance similar to binary search trees by using a random number of forward links to skip parts of the list.
|
||||
|
||||
## Splay Tree
|
||||
|
||||
A [splay tree](http://en.wikipedia.org/wiki/Splay_tree) is a type of binary search tree where every access to the tree results in the tree being rearranged so that the current node gets put on top.
|
||||
|
||||
## Stack
|
||||
A [stack](http://en.wikipedia.org/wiki/Stack_(abstract_data_type%29) is a last-in last-out data structure.
|
||||
|
||||
## Trie
|
||||
A [trie](http://en.wikipedia.org/wiki/Trie) is a type of tree where each node represents one byte of a key.
|
||||
|
||||
## Ternary Search Tree
|
||||
|
||||
A [ternary search tree](http://en.wikipedia.org/wiki/Ternary_search_tree) is similar to a trie in that nodes store the letters of the key, but instead of either using a list or hash at each node a binary tree is used. Ternary search trees have the performance benefits of a trie without the usual memory costs.
|
27
vendor/github.com/golang-collections/collections/collections.go
generated
vendored
Normal file
27
vendor/github.com/golang-collections/collections/collections.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package collections
|
||||
|
||||
type (
|
||||
Collection interface {
|
||||
Do(func(interface{})bool)
|
||||
}
|
||||
)
|
||||
|
||||
func GetRange(c Collection, start, length int) []interface{} {
|
||||
end := start + length
|
||||
items := make([]interface{}, length)
|
||||
i := 0
|
||||
j := 0
|
||||
c.Do(func(item interface{})bool{
|
||||
if i >= start {
|
||||
if i < end {
|
||||
items[j] = item
|
||||
j++
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
i++
|
||||
return true
|
||||
})
|
||||
return items[:j]
|
||||
}
|
52
vendor/github.com/golang-collections/collections/grid/grid.go
generated
vendored
Normal file
52
vendor/github.com/golang-collections/collections/grid/grid.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package grid
|
||||
|
||||
import (
|
||||
. "github.com/badgerodon/collections"
|
||||
)
|
||||
|
||||
type (
|
||||
Grid struct {
|
||||
values []interface{}
|
||||
cols, rows int
|
||||
}
|
||||
)
|
||||
|
||||
func New(cols, rows int) *Grid {
|
||||
return &Grid{
|
||||
values: make([]interface{}, cols*rows),
|
||||
cols: cols,
|
||||
rows: rows,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Grid) Do(f func(p Point, value interface{})) {
|
||||
for x := 0; x < this.cols; x++ {
|
||||
for y := 0; y < this.rows; y++ {
|
||||
f(Point{x, y}, this.values[x*this.cols+y])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Grid) Get(p Point) interface{} {
|
||||
if p.X < 0 || p.Y < 0 || p.X >= this.cols || p.Y >= this.rows {
|
||||
return nil
|
||||
}
|
||||
v, _ := this.values[p.X*this.cols+p.Y]
|
||||
return v
|
||||
}
|
||||
|
||||
func (this *Grid) Rows() int {
|
||||
return this.rows
|
||||
}
|
||||
|
||||
func (this *Grid) Cols() int {
|
||||
return this.cols
|
||||
}
|
||||
|
||||
func (this *Grid) Len() int {
|
||||
return this.rows * this.cols
|
||||
}
|
||||
|
||||
func (this *Grid) Set(p Point, v interface{}) {
|
||||
|
||||
}
|
7
vendor/github.com/golang-collections/collections/point.go
generated
vendored
Normal file
7
vendor/github.com/golang-collections/collections/point.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package collections
|
||||
|
||||
type (
|
||||
Point struct {
|
||||
X, Y int
|
||||
}
|
||||
)
|
55
vendor/github.com/golang-collections/collections/queue/queue.go
generated
vendored
Normal file
55
vendor/github.com/golang-collections/collections/queue/queue.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package queue
|
||||
|
||||
type (
|
||||
Queue struct {
|
||||
start, end *node
|
||||
length int
|
||||
}
|
||||
node struct {
|
||||
value interface{}
|
||||
next *node
|
||||
}
|
||||
)
|
||||
|
||||
// Create a new queue
|
||||
func New() *Queue {
|
||||
return &Queue{nil,nil,0}
|
||||
}
|
||||
// Take the next item off the front of the queue
|
||||
func (this *Queue) Dequeue() interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
n := this.start
|
||||
if this.length == 1 {
|
||||
this.start = nil
|
||||
this.end = nil
|
||||
} else {
|
||||
this.start = this.start.next
|
||||
}
|
||||
this.length--
|
||||
return n.value
|
||||
}
|
||||
// Put an item on the end of a queue
|
||||
func (this *Queue) Enqueue(value interface{}) {
|
||||
n := &node{value,nil}
|
||||
if this.length == 0 {
|
||||
this.start = n
|
||||
this.end = n
|
||||
} else {
|
||||
this.end.next = n
|
||||
this.end = n
|
||||
}
|
||||
this.length++
|
||||
}
|
||||
// Return the number of items in the queue
|
||||
func (this *Queue) Len() int {
|
||||
return this.length
|
||||
}
|
||||
// Return the first item in the queue without removing it
|
||||
func (this *Queue) Peek() interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
return this.start.value
|
||||
}
|
50
vendor/github.com/golang-collections/collections/queue/queue_test.go
generated
vendored
Normal file
50
vendor/github.com/golang-collections/collections/queue/queue_test.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
q := New()
|
||||
|
||||
if q.Len() != 0 {
|
||||
t.Errorf("Length should be 0")
|
||||
}
|
||||
|
||||
q.Enqueue(1)
|
||||
|
||||
if q.Len() != 1 {
|
||||
t.Errorf("Length should be 1")
|
||||
}
|
||||
|
||||
if q.Peek().(int) != 1 {
|
||||
t.Errorf("Enqueued value should be 1")
|
||||
}
|
||||
|
||||
v := q.Dequeue()
|
||||
|
||||
if v.(int) != 1 {
|
||||
t.Errorf("Dequeued value should be 1")
|
||||
}
|
||||
|
||||
if q.Peek() != nil || q.Dequeue() != nil {
|
||||
t.Errorf("Empty queue should have no values")
|
||||
}
|
||||
|
||||
q.Enqueue(1)
|
||||
q.Enqueue(2)
|
||||
|
||||
if q.Len() != 2 {
|
||||
t.Errorf("Length should be 2")
|
||||
}
|
||||
|
||||
if q.Peek().(int) != 1 {
|
||||
t.Errorf("First value should be 1")
|
||||
}
|
||||
|
||||
q.Dequeue()
|
||||
|
||||
if q.Peek().(int) != 2 {
|
||||
t.Errorf("Next value should be 2")
|
||||
}
|
||||
}
|
106
vendor/github.com/golang-collections/collections/set/set.go
generated
vendored
Executable file
106
vendor/github.com/golang-collections/collections/set/set.go
generated
vendored
Executable file
@@ -0,0 +1,106 @@
|
||||
package set
|
||||
|
||||
type (
|
||||
Set struct {
|
||||
hash map[interface{}]nothing
|
||||
}
|
||||
|
||||
nothing struct{}
|
||||
)
|
||||
|
||||
// Create a new set
|
||||
func New(initial ...interface{}) *Set {
|
||||
s := &Set{make(map[interface{}]nothing)}
|
||||
|
||||
for _, v := range initial {
|
||||
s.Insert(v)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Find the difference between two sets
|
||||
func (this *Set) Difference(set *Set) *Set {
|
||||
n := make(map[interface{}]nothing)
|
||||
|
||||
for k, _ := range this.hash {
|
||||
if _, exists := set.hash[k]; !exists {
|
||||
n[k] = nothing{}
|
||||
}
|
||||
}
|
||||
|
||||
return &Set{n}
|
||||
}
|
||||
|
||||
// Call f for each item in the set
|
||||
func (this *Set) Do(f func(interface{})) {
|
||||
for k, _ := range this.hash {
|
||||
f(k)
|
||||
}
|
||||
}
|
||||
|
||||
// Test to see whether or not the element is in the set
|
||||
func (this *Set) Has(element interface{}) bool {
|
||||
_, exists := this.hash[element]
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add an element to the set
|
||||
func (this *Set) Insert(element interface{}) {
|
||||
this.hash[element] = nothing{}
|
||||
}
|
||||
|
||||
// Find the intersection of two sets
|
||||
func (this *Set) Intersection(set *Set) *Set {
|
||||
n := make(map[interface{}]nothing)
|
||||
|
||||
for k, _ := range this.hash {
|
||||
if _, exists := set.hash[k]; exists {
|
||||
n[k] = nothing{}
|
||||
}
|
||||
}
|
||||
|
||||
return &Set{n}
|
||||
}
|
||||
|
||||
// Return the number of items in the set
|
||||
func (this *Set) Len() int {
|
||||
return len(this.hash)
|
||||
}
|
||||
|
||||
// Test whether or not this set is a proper subset of "set"
|
||||
func (this *Set) ProperSubsetOf(set *Set) bool {
|
||||
return this.SubsetOf(set) && this.Len() < set.Len()
|
||||
}
|
||||
|
||||
// Remove an element from the set
|
||||
func (this *Set) Remove(element interface{}) {
|
||||
delete(this.hash, element)
|
||||
}
|
||||
|
||||
// Test whether or not this set is a subset of "set"
|
||||
func (this *Set) SubsetOf(set *Set) bool {
|
||||
if this.Len() > set.Len() {
|
||||
return false
|
||||
}
|
||||
for k, _ := range this.hash {
|
||||
if _, exists := set.hash[k]; !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Find the union of two sets
|
||||
func (this *Set) Union(set *Set) *Set {
|
||||
n := make(map[interface{}]nothing)
|
||||
|
||||
for k, _ := range this.hash {
|
||||
n[k] = nothing{}
|
||||
}
|
||||
for k, _ := range set.hash {
|
||||
n[k] = nothing{}
|
||||
}
|
||||
|
||||
return &Set{n}
|
||||
}
|
74
vendor/github.com/golang-collections/collections/set/set_test.go
generated
vendored
Normal file
74
vendor/github.com/golang-collections/collections/set/set_test.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
s := New()
|
||||
|
||||
s.Insert(5)
|
||||
|
||||
if s.Len() != 1 {
|
||||
t.Errorf("Length should be 1")
|
||||
}
|
||||
|
||||
if !s.Has(5) {
|
||||
t.Errorf("Membership test failed")
|
||||
}
|
||||
|
||||
s.Remove(5)
|
||||
|
||||
if s.Len() != 0 {
|
||||
t.Errorf("Length should be 0")
|
||||
}
|
||||
|
||||
if s.Has(5) {
|
||||
t.Errorf("The set should be empty")
|
||||
}
|
||||
|
||||
// Difference
|
||||
s1 := New(1,2,3,4,5,6)
|
||||
s2 := New(4,5,6)
|
||||
s3 := s1.Difference(s2)
|
||||
|
||||
if s3.Len() != 3 {
|
||||
t.Errorf("Length should be 3")
|
||||
}
|
||||
|
||||
if !(s3.Has(1) && s3.Has(2) && s3.Has(3)) {
|
||||
t.Errorf("Set should only contain 1, 2, 3")
|
||||
}
|
||||
|
||||
// Intersection
|
||||
s3 = s1.Intersection(s2)
|
||||
if s3.Len() != 3 {
|
||||
t.Errorf("Length should be 3 after intersection")
|
||||
}
|
||||
|
||||
if !(s3.Has(4) && s3.Has(5) && s3.Has(6)) {
|
||||
t.Errorf("Set should contain 4, 5, 6")
|
||||
}
|
||||
|
||||
// Union
|
||||
s4 := New(7,8,9)
|
||||
s3 = s2.Union(s4)
|
||||
|
||||
if s3.Len() != 6 {
|
||||
t.Errorf("Length should be 6 after union")
|
||||
}
|
||||
|
||||
if !(s3.Has(7)) {
|
||||
t.Errorf("Set should contain 4, 5, 6, 7, 8, 9")
|
||||
}
|
||||
|
||||
// Subset
|
||||
if !s1.SubsetOf(s1) {
|
||||
t.Errorf("set should be a subset of itself")
|
||||
}
|
||||
// Proper Subset
|
||||
if s1.ProperSubsetOf(s1) {
|
||||
t.Errorf("set should not be a subset of itself")
|
||||
}
|
||||
|
||||
}
|
171
vendor/github.com/golang-collections/collections/skip/skip.go
generated
vendored
Normal file
171
vendor/github.com/golang-collections/collections/skip/skip.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
package skip
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
node struct {
|
||||
next []*node
|
||||
key interface{}
|
||||
value interface{}
|
||||
}
|
||||
SkipList struct {
|
||||
root *node
|
||||
size int
|
||||
less func(interface{},interface{})bool
|
||||
gen *rand.Rand
|
||||
probability float64
|
||||
}
|
||||
)
|
||||
// Create a new skip list
|
||||
func New(less func(interface{},interface{})bool) *SkipList {
|
||||
gen := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
n := &node{make([]*node, 0),nil,nil}
|
||||
return &SkipList{n, 0, less, gen, 0.75}
|
||||
}
|
||||
func (this *SkipList) Do(f func(interface{}, interface{})bool) {
|
||||
if this.size == 0 {
|
||||
return
|
||||
}
|
||||
cur := this.root.next[0]
|
||||
for cur != nil {
|
||||
if !f(cur.key, cur.value) {
|
||||
break
|
||||
}
|
||||
cur = cur.next[0]
|
||||
}
|
||||
}
|
||||
// Get an item from the skip list
|
||||
func (this *SkipList) Get(key interface{}) interface{} {
|
||||
if this.size == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
cur := this.root
|
||||
// Start at the top
|
||||
for i := len(cur.next)-1; i >= 0; i-- {
|
||||
for this.less(cur.next[i].key, key) {
|
||||
cur = cur.next[i]
|
||||
}
|
||||
}
|
||||
cur = cur.next[0]
|
||||
|
||||
if this.equals(cur.key, key) {
|
||||
return cur.value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// Insert a new item into the skip list
|
||||
func (this *SkipList) Insert(key interface{}, value interface{}) {
|
||||
prev := this.getPrevious(key)
|
||||
|
||||
// Already in the list so just update the value
|
||||
if len(prev) > 0 && prev[0].next[0] != nil && this.equals(prev[0].next[0].key, key) {
|
||||
prev[0].next[0].value = value
|
||||
return
|
||||
}
|
||||
|
||||
h := len(this.root.next)
|
||||
nh := this.pickHeight()
|
||||
n := &node{make([]*node, nh),key,value}
|
||||
|
||||
// Higher than anything seen before, so tack it on top
|
||||
if nh > h {
|
||||
this.root.next = append(this.root.next, n)
|
||||
}
|
||||
|
||||
// Update the previous nodes
|
||||
for i := 0; i < h && i < nh; i++ {
|
||||
n.next[i] = prev[i].next[i]
|
||||
prev[i].next[i] = n
|
||||
}
|
||||
|
||||
this.size++
|
||||
}
|
||||
// Get the length of the skip list
|
||||
func (this *SkipList) Len() int {
|
||||
return this.size
|
||||
}
|
||||
// Remove an item from the skip list
|
||||
func (this *SkipList) Remove(key interface{}) interface{} {
|
||||
prev := this.getPrevious(key)
|
||||
if len(prev) == 0 {
|
||||
return nil
|
||||
}
|
||||
cur := prev[0].next[0]
|
||||
|
||||
// If we found it
|
||||
if cur != nil && this.equals(key, cur.key) {
|
||||
// Change all the linked lists
|
||||
for i := 0; i < len(prev); i++ {
|
||||
if prev[i] != nil && prev[i].next[i] != nil {
|
||||
prev[i].next[i] = cur.next[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Kill off the upper links if they're nil
|
||||
for i := len(this.root.next)-1; i>=0; i-- {
|
||||
if this.root.next[i] == nil {
|
||||
this.root.next = this.root.next[:i]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.size--
|
||||
|
||||
return cur.value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// String representation of the list
|
||||
func (this *SkipList) String() string {
|
||||
str := "{"
|
||||
if len(this.root.next) > 0 {
|
||||
cur := this.root.next[0]
|
||||
for cur != nil {
|
||||
str += fmt.Sprint(cur.key)
|
||||
str += ":"
|
||||
str += fmt.Sprint(cur.value)
|
||||
str += " "
|
||||
cur = cur.next[0]
|
||||
}
|
||||
}
|
||||
str += "}"
|
||||
|
||||
return str
|
||||
}
|
||||
// Get a vertical list of nodes of all the things that occur
|
||||
// immediately before "key"
|
||||
func (this *SkipList) getPrevious(key interface{}) []*node {
|
||||
cur := this.root
|
||||
h := len(cur.next)
|
||||
nodes := make([]*node, h)
|
||||
for i := h-1; i >= 0; i-- {
|
||||
for cur.next[i] != nil && this.less(cur.next[i].key, key) {
|
||||
cur = cur.next[i]
|
||||
}
|
||||
nodes[i] = cur
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
// Defines an equals method in terms of "less"
|
||||
func (this *SkipList) equals(a, b interface{}) bool {
|
||||
return !this.less(a,b) && !this.less(b,a)
|
||||
}
|
||||
// Pick a random height
|
||||
func (this *SkipList) pickHeight() int {
|
||||
h := 1
|
||||
for this.gen.Float64() > this.probability {
|
||||
h++
|
||||
}
|
||||
if h > len(this.root.next) {
|
||||
return h + 1
|
||||
}
|
||||
return h
|
||||
}
|
38
vendor/github.com/golang-collections/collections/skip/skip_test.go
generated
vendored
Normal file
38
vendor/github.com/golang-collections/collections/skip/skip_test.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package skip
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
sl := New(func(a,b interface{})bool {
|
||||
return a.(int) < b.(int)
|
||||
})
|
||||
sl.Insert(1, 100)
|
||||
if sl.Len() != 1 {
|
||||
t.Errorf("expecting len 1")
|
||||
}
|
||||
sl.Insert(1, 1000)
|
||||
if sl.Len() != 1 {
|
||||
t.Errorf("expecting len 1")
|
||||
}
|
||||
if sl.Get(1).(int) != 1000 {
|
||||
t.Errorf("expecting sl[1] == 1000")
|
||||
}
|
||||
sl.Remove(1)
|
||||
if sl.Len() != 0 {
|
||||
t.Errorf("expecting len 0")
|
||||
}
|
||||
|
||||
sl.Insert(2, 200)
|
||||
sl.Insert(1, 100)
|
||||
vs := make([]int, 0)
|
||||
sl.Do(func(k, v interface{}) bool {
|
||||
vs = append(vs, k.(int))
|
||||
return true
|
||||
})
|
||||
if len(vs) != 2 || vs[0] != 1 || vs[1] != 2 {
|
||||
t.Errorf("expecting sorted iteration of all keys")
|
||||
}
|
||||
}
|
487
vendor/github.com/golang-collections/collections/splay/splay.go
generated
vendored
Normal file
487
vendor/github.com/golang-collections/collections/splay/splay.go
generated
vendored
Normal file
@@ -0,0 +1,487 @@
|
||||
package splay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
Any interface{}
|
||||
LessFunc func(interface{}, interface{}) bool
|
||||
VisitFunc func(interface{}) bool
|
||||
|
||||
node struct {
|
||||
value Any
|
||||
parent, left, right *node
|
||||
}
|
||||
nodei struct {
|
||||
step int
|
||||
node *node
|
||||
prev *nodei
|
||||
}
|
||||
|
||||
SplayTree struct {
|
||||
length int
|
||||
root *node
|
||||
less LessFunc
|
||||
}
|
||||
)
|
||||
|
||||
// Create a new splay tree, using the less function to determine the order.
|
||||
func New(less LessFunc) *SplayTree {
|
||||
return &SplayTree{0, nil, less}
|
||||
}
|
||||
|
||||
// Get the first value from the collection. Returns nil if empty.
|
||||
func (this *SplayTree) First() Any {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := this.root
|
||||
for n.left != nil {
|
||||
n = n.left
|
||||
}
|
||||
return n.value
|
||||
}
|
||||
|
||||
// Get the last value from the collection. Returns nil if empty.
|
||||
func (this *SplayTree) Last() Any {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
n := this.root
|
||||
for n.right != nil {
|
||||
n = n.right
|
||||
}
|
||||
return n.value
|
||||
}
|
||||
|
||||
// Get an item from the splay tree
|
||||
func (this *SplayTree) Get(item Any) Any {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := this.root
|
||||
for n != nil {
|
||||
if this.less(item, n.value) {
|
||||
n = n.left
|
||||
continue
|
||||
}
|
||||
|
||||
if this.less(n.value, item) {
|
||||
n = n.right
|
||||
continue
|
||||
}
|
||||
|
||||
this.splay(n)
|
||||
return n.value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (this *SplayTree) Has(value Any) bool {
|
||||
return this.Get(value) != nil
|
||||
}
|
||||
func (this *SplayTree) Init() {
|
||||
this.length = 0
|
||||
this.root = nil
|
||||
}
|
||||
func (this *SplayTree) Add(value Any) {
|
||||
if this.length == 0 {
|
||||
this.root = &node{value, nil, nil, nil}
|
||||
this.length = 1
|
||||
return
|
||||
}
|
||||
|
||||
n := this.root
|
||||
for {
|
||||
if this.less(value, n.value) {
|
||||
if n.left == nil {
|
||||
n.left = &node{value, n, nil, nil}
|
||||
this.length++
|
||||
n = n.left
|
||||
break
|
||||
}
|
||||
n = n.left
|
||||
continue
|
||||
}
|
||||
|
||||
if this.less(n.value, value) {
|
||||
if n.right == nil {
|
||||
n.right = &node{value, n, nil, nil}
|
||||
this.length++
|
||||
n = n.right
|
||||
break
|
||||
}
|
||||
n = n.right
|
||||
continue
|
||||
}
|
||||
|
||||
n.value = value
|
||||
break
|
||||
}
|
||||
this.splay(n)
|
||||
}
|
||||
func (this *SplayTree) PreOrder(visit VisitFunc) {
|
||||
if this.length == 1 {
|
||||
return
|
||||
}
|
||||
i := &nodei{0, this.root, nil}
|
||||
for i != nil {
|
||||
switch i.step {
|
||||
// Value
|
||||
case 0:
|
||||
i.step++
|
||||
if !visit(i.node.value) {
|
||||
break
|
||||
}
|
||||
// Left
|
||||
case 1:
|
||||
i.step++
|
||||
if i.node.left != nil {
|
||||
i = &nodei{0, i.node.left, i}
|
||||
}
|
||||
// Right
|
||||
case 2:
|
||||
i.step++
|
||||
if i.node.right != nil {
|
||||
i = &nodei{0, i.node.right, i}
|
||||
}
|
||||
default:
|
||||
i = i.prev
|
||||
}
|
||||
}
|
||||
}
|
||||
func (this *SplayTree) InOrder(visit VisitFunc) {
|
||||
if this.length == 1 {
|
||||
return
|
||||
}
|
||||
i := &nodei{0, this.root, nil}
|
||||
for i != nil {
|
||||
switch i.step {
|
||||
// Left
|
||||
case 0:
|
||||
i.step++
|
||||
if i.node.left != nil {
|
||||
i = &nodei{0, i.node.left, i}
|
||||
}
|
||||
// Value
|
||||
case 1:
|
||||
i.step++
|
||||
if !visit(i.node.value) {
|
||||
break
|
||||
}
|
||||
// Right
|
||||
case 2:
|
||||
i.step++
|
||||
if i.node.right != nil {
|
||||
i = &nodei{0, i.node.right, i}
|
||||
}
|
||||
default:
|
||||
i = i.prev
|
||||
}
|
||||
}
|
||||
}
|
||||
func (this *SplayTree) PostOrder(visit VisitFunc) {
|
||||
if this.length == 1 {
|
||||
return
|
||||
}
|
||||
i := &nodei{0, this.root, nil}
|
||||
for i != nil {
|
||||
switch i.step {
|
||||
// Left
|
||||
case 0:
|
||||
i.step++
|
||||
if i.node.left != nil {
|
||||
i = &nodei{0, i.node.left, i}
|
||||
}
|
||||
// Right
|
||||
case 1:
|
||||
i.step++
|
||||
if i.node.right != nil {
|
||||
i = &nodei{0, i.node.right, i}
|
||||
}
|
||||
// Value
|
||||
case 2:
|
||||
i.step++
|
||||
if !visit(i.node.value) {
|
||||
break
|
||||
}
|
||||
default:
|
||||
i = i.prev
|
||||
}
|
||||
}
|
||||
}
|
||||
func (this *SplayTree) Do(visit VisitFunc) {
|
||||
this.InOrder(visit)
|
||||
}
|
||||
func (this *SplayTree) Len() int {
|
||||
return this.length
|
||||
}
|
||||
func (this *SplayTree) Remove(value Any) {
|
||||
if this.length == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
n := this.root
|
||||
for n != nil {
|
||||
if this.less(value, n.value) {
|
||||
n = n.left
|
||||
continue
|
||||
}
|
||||
if this.less(n.value, value) {
|
||||
n = n.right
|
||||
continue
|
||||
}
|
||||
|
||||
// First splay the parent node
|
||||
if n.parent != nil {
|
||||
this.splay(n.parent)
|
||||
}
|
||||
|
||||
// No children
|
||||
if n.left == nil && n.right == nil {
|
||||
// guess we're the root node
|
||||
if n.parent == nil {
|
||||
this.root = nil
|
||||
break
|
||||
}
|
||||
if n.parent.left == n {
|
||||
n.parent.left = nil
|
||||
} else {
|
||||
n.parent.right = nil
|
||||
}
|
||||
} else if n.left == nil {
|
||||
// root node
|
||||
if n.parent == nil {
|
||||
this.root = n.right
|
||||
break
|
||||
}
|
||||
if n.parent.left == n {
|
||||
n.parent.left = n.right
|
||||
} else {
|
||||
n.parent.right = n.right
|
||||
}
|
||||
} else if n.right == nil {
|
||||
// root node
|
||||
if n.parent == nil {
|
||||
this.root = n.left
|
||||
break
|
||||
}
|
||||
if n.parent.left == n {
|
||||
n.parent.left = n.left
|
||||
} else {
|
||||
n.parent.right = n.left
|
||||
}
|
||||
} else {
|
||||
// find the successor
|
||||
s := n.right
|
||||
for s.left != nil {
|
||||
s = s.left
|
||||
}
|
||||
|
||||
np := n.parent
|
||||
nl := n.left
|
||||
nr := n.right
|
||||
|
||||
sp := s.parent
|
||||
sr := s.right
|
||||
|
||||
// Update parent
|
||||
s.parent = np
|
||||
if np == nil {
|
||||
this.root = s
|
||||
} else {
|
||||
if np.left == n {
|
||||
np.left = s
|
||||
} else {
|
||||
np.right = s
|
||||
}
|
||||
}
|
||||
|
||||
// Update left
|
||||
s.left = nl
|
||||
s.left.parent = s
|
||||
|
||||
// Update right
|
||||
if nr != s {
|
||||
s.right = nr
|
||||
s.right.parent = s
|
||||
}
|
||||
|
||||
// Update successor parent
|
||||
if sp.left == s {
|
||||
sp.left = sr
|
||||
} else {
|
||||
sp.right = sr
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if n != nil {
|
||||
this.length--
|
||||
}
|
||||
}
|
||||
func (this *SplayTree) String() string {
|
||||
if this.length == 0 {
|
||||
return "{}"
|
||||
}
|
||||
return this.root.String()
|
||||
}
|
||||
|
||||
// Splay a node in the tree (send it to the top)
|
||||
func (this *SplayTree) splay(n *node) {
|
||||
// Already root, nothing to do
|
||||
if n.parent == nil {
|
||||
this.root = n
|
||||
return
|
||||
}
|
||||
|
||||
p := n.parent
|
||||
g := p.parent
|
||||
|
||||
// Zig
|
||||
if p == this.root {
|
||||
if n == p.left {
|
||||
p.rotateRight()
|
||||
} else {
|
||||
p.rotateLeft()
|
||||
}
|
||||
} else {
|
||||
// Zig-zig
|
||||
if n == p.left && p == g.left {
|
||||
g.rotateRight()
|
||||
p.rotateRight()
|
||||
} else if n == p.right && p == g.right {
|
||||
g.rotateLeft()
|
||||
p.rotateLeft()
|
||||
// Zig-zag
|
||||
} else if n == p.right && p == g.left {
|
||||
p.rotateLeft()
|
||||
g.rotateRight()
|
||||
} else if n == p.left && p == g.right {
|
||||
p.rotateRight()
|
||||
g.rotateLeft()
|
||||
}
|
||||
}
|
||||
this.splay(n)
|
||||
}
|
||||
|
||||
// Swap two nodes in the tree
|
||||
func (this *SplayTree) swap(n1, n2 *node) {
|
||||
p1 := n1.parent
|
||||
l1 := n1.left
|
||||
r1 := n1.right
|
||||
|
||||
p2 := n2.parent
|
||||
l2 := n2.left
|
||||
r2 := n2.right
|
||||
|
||||
// Update node links
|
||||
n1.parent = p2
|
||||
n1.left = l2
|
||||
n1.right = r2
|
||||
|
||||
n2.parent = p1
|
||||
n2.left = l1
|
||||
n2.right = r1
|
||||
|
||||
// Update parent links
|
||||
if p1 != nil {
|
||||
if p1.left == n1 {
|
||||
p1.left = n2
|
||||
} else {
|
||||
p1.right = n2
|
||||
}
|
||||
}
|
||||
if p2 != nil {
|
||||
if p2.left == n2 {
|
||||
p2.left = n1
|
||||
} else {
|
||||
p2.right = n1
|
||||
}
|
||||
}
|
||||
|
||||
if n1 == this.root {
|
||||
this.root = n2
|
||||
} else if n2 == this.root {
|
||||
this.root = n1
|
||||
}
|
||||
}
|
||||
|
||||
// Node methods
|
||||
func (this *node) String() string {
|
||||
str := "{" + fmt.Sprint(this.value) + "|"
|
||||
if this.left != nil {
|
||||
str += this.left.String()
|
||||
}
|
||||
str += "|"
|
||||
if this.right != nil {
|
||||
str += this.right.String()
|
||||
}
|
||||
str += "}"
|
||||
return str
|
||||
}
|
||||
func (this *node) rotateLeft() {
|
||||
parent := this.parent
|
||||
pivot := this.right
|
||||
child := pivot.left
|
||||
|
||||
if pivot == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Update the parent
|
||||
if parent != nil {
|
||||
if parent.left == this {
|
||||
parent.left = pivot
|
||||
} else {
|
||||
parent.right = pivot
|
||||
}
|
||||
}
|
||||
|
||||
// Update the pivot
|
||||
pivot.parent = parent
|
||||
pivot.left = this
|
||||
|
||||
// Update the child
|
||||
if child != nil {
|
||||
child.parent = this
|
||||
}
|
||||
|
||||
// Update this
|
||||
this.parent = pivot
|
||||
this.right = child
|
||||
}
|
||||
func (this *node) rotateRight() {
|
||||
parent := this.parent
|
||||
pivot := this.left
|
||||
child := pivot.right
|
||||
|
||||
if pivot == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Update the parent
|
||||
if parent != nil {
|
||||
if parent.left == this {
|
||||
parent.left = pivot
|
||||
} else {
|
||||
parent.right = pivot
|
||||
}
|
||||
}
|
||||
|
||||
// Update the pivot
|
||||
pivot.parent = parent
|
||||
pivot.right = this
|
||||
|
||||
if child != nil {
|
||||
child.parent = this
|
||||
}
|
||||
|
||||
// Update this
|
||||
this.parent = pivot
|
||||
this.left = child
|
||||
}
|
27
vendor/github.com/golang-collections/collections/splay/splay_test.go
generated
vendored
Normal file
27
vendor/github.com/golang-collections/collections/splay/splay_test.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package splay
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
tree := New(func(a,b interface{})bool {
|
||||
return a.(string) < b.(string)
|
||||
})
|
||||
|
||||
tree.Insert("d", 4)
|
||||
tree.Insert("b", 2)
|
||||
tree.Insert("a", 1)
|
||||
tree.Insert("c", 3)
|
||||
|
||||
if tree.Len() != 4 {
|
||||
t.Errorf("expecting len 4")
|
||||
}
|
||||
|
||||
tree.Remove("b")
|
||||
|
||||
if tree.Len() != 3 {
|
||||
t.Errorf("expecting len 3")
|
||||
}
|
||||
}
|
44
vendor/github.com/golang-collections/collections/stack/stack.go
generated
vendored
Normal file
44
vendor/github.com/golang-collections/collections/stack/stack.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package stack
|
||||
|
||||
type (
|
||||
Stack struct {
|
||||
top *node
|
||||
length int
|
||||
}
|
||||
node struct {
|
||||
value interface{}
|
||||
prev *node
|
||||
}
|
||||
)
|
||||
// Create a new stack
|
||||
func New() *Stack {
|
||||
return &Stack{nil,0}
|
||||
}
|
||||
// Return the number of items in the stack
|
||||
func (this *Stack) Len() int {
|
||||
return this.length
|
||||
}
|
||||
// View the top item on the stack
|
||||
func (this *Stack) Peek() interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
return this.top.value
|
||||
}
|
||||
// Pop the top item of the stack and return it
|
||||
func (this *Stack) Pop() interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := this.top
|
||||
this.top = n.prev
|
||||
this.length--
|
||||
return n.value
|
||||
}
|
||||
// Push a value onto the top of the stack
|
||||
func (this *Stack) Push(value interface{}) {
|
||||
n := &node{value,this.top}
|
||||
this.top = n
|
||||
this.length++
|
||||
}
|
42
vendor/github.com/golang-collections/collections/stack/stack_test.go
generated
vendored
Normal file
42
vendor/github.com/golang-collections/collections/stack/stack_test.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package stack
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
s := New()
|
||||
|
||||
if s.Len() != 0 {
|
||||
t.Errorf("Length of an empty stack should be 0")
|
||||
}
|
||||
|
||||
s.Push(1)
|
||||
|
||||
if s.Len() != 1 {
|
||||
t.Errorf("Length should be 0")
|
||||
}
|
||||
|
||||
if s.Peek().(int) != 1 {
|
||||
t.Errorf("Top item on the stack should be 1")
|
||||
}
|
||||
|
||||
if s.Pop().(int) != 1 {
|
||||
t.Errorf("Top item should have been 1")
|
||||
}
|
||||
|
||||
if s.Len() != 0 {
|
||||
t.Errorf("Stack should be empty")
|
||||
}
|
||||
|
||||
s.Push(1)
|
||||
s.Push(2)
|
||||
|
||||
if s.Len() != 2 {
|
||||
t.Errorf("Length should be 2")
|
||||
}
|
||||
|
||||
if s.Peek().(int) != 2 {
|
||||
t.Errorf("Top of the stack should be 2")
|
||||
}
|
||||
}
|
148
vendor/github.com/golang-collections/collections/trie/trie.go
generated
vendored
Normal file
148
vendor/github.com/golang-collections/collections/trie/trie.go
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
package trie
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
Trie struct {
|
||||
root *node
|
||||
size int
|
||||
}
|
||||
node struct {
|
||||
key interface{}
|
||||
value interface{}
|
||||
next [256]*node
|
||||
}
|
||||
iterator struct {
|
||||
step int
|
||||
node *node
|
||||
prev *iterator
|
||||
}
|
||||
)
|
||||
|
||||
func toBytes(obj interface{}) []byte {
|
||||
switch o := obj.(type) {
|
||||
case []byte:
|
||||
return o
|
||||
case string:
|
||||
return []byte(o)
|
||||
}
|
||||
return []byte(fmt.Sprint(obj))
|
||||
}
|
||||
|
||||
func New() *Trie {
|
||||
return &Trie{nil,0}
|
||||
}
|
||||
func (this *Trie) Do(handler func(interface{},interface{})bool) {
|
||||
if this.size > 0 {
|
||||
this.root.do(handler)
|
||||
}
|
||||
}
|
||||
func (this *Trie) Get(key interface{}) interface{} {
|
||||
if this.size == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
bs := toBytes(key)
|
||||
cur := this.root
|
||||
for i := 0; i < len(bs); i++ {
|
||||
if cur.next[bs[i]] != nil {
|
||||
cur = cur.next[bs[i]]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return cur.value
|
||||
}
|
||||
func (this *Trie) Has(key interface{}) bool {
|
||||
return this.Get(key) != nil
|
||||
}
|
||||
func (this *Trie) Init() {
|
||||
this.root = nil
|
||||
this.size = 0
|
||||
}
|
||||
func (this *Trie) Insert(key interface{}, value interface{}) {
|
||||
if this.size == 0 {
|
||||
this.root = newNode()
|
||||
}
|
||||
|
||||
bs := toBytes(key)
|
||||
cur := this.root
|
||||
for i := 0; i < len(bs); i++ {
|
||||
if cur.next[bs[i]] != nil {
|
||||
cur = cur.next[bs[i]]
|
||||
} else {
|
||||
cur.next[bs[i]] = newNode()
|
||||
cur = cur.next[bs[i]]
|
||||
}
|
||||
}
|
||||
if cur.key == nil {
|
||||
this.size++
|
||||
}
|
||||
cur.key = key
|
||||
cur.value = value
|
||||
}
|
||||
func (this *Trie) Len() int {
|
||||
return this.size
|
||||
}
|
||||
func (this *Trie) Remove(key interface{}) interface{} {
|
||||
if this.size == 0 {
|
||||
return nil
|
||||
}
|
||||
bs := toBytes(key)
|
||||
cur := this.root
|
||||
|
||||
for i := 0; i < len(bs); i++ {
|
||||
if cur.next[bs[i]] != nil {
|
||||
cur = cur.next[bs[i]]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cleanup dead nodes
|
||||
|
||||
val := cur.value
|
||||
|
||||
if cur.value != nil {
|
||||
this.size--
|
||||
cur.value = nil
|
||||
cur.key = nil
|
||||
}
|
||||
return val
|
||||
}
|
||||
func (this *Trie) String() string {
|
||||
str := "{"
|
||||
i := 0
|
||||
this.Do(func(k, v interface{}) bool {
|
||||
if i > 0 {
|
||||
str += ", "
|
||||
}
|
||||
str += fmt.Sprint(k, ":", v)
|
||||
i++
|
||||
return true
|
||||
})
|
||||
str += "}"
|
||||
return str
|
||||
}
|
||||
|
||||
func newNode() *node {
|
||||
var next [256]*node
|
||||
return &node{nil,nil,next}
|
||||
}
|
||||
func (this *node) do(handler func(interface{}, interface{}) bool) bool {
|
||||
for i := 0; i < 256; i++ {
|
||||
if this.next[i] != nil {
|
||||
if this.next[i].key != nil {
|
||||
if !handler(this.next[i].key, this.next[i].value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if !this.next[i].do(handler) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
31
vendor/github.com/golang-collections/collections/trie/trie_test.go
generated
vendored
Normal file
31
vendor/github.com/golang-collections/collections/trie/trie_test.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package trie
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
x := New()
|
||||
x.Insert(1, 100)
|
||||
if x.Len() != 1 {
|
||||
t.Errorf("expected len 1")
|
||||
}
|
||||
if x.Get(1).(int) != 100 {
|
||||
t.Errorf("expected to get 100 for 1")
|
||||
}
|
||||
x.Remove(1)
|
||||
if x.Len() != 0 {
|
||||
t.Errorf("expected len 0")
|
||||
}
|
||||
x.Insert(2, 200)
|
||||
x.Insert(1, 100)
|
||||
vs := make([]int, 0)
|
||||
x.Do(func(k, v interface{}) bool {
|
||||
vs = append(vs, k.(int))
|
||||
return true
|
||||
})
|
||||
if len(vs) != 2 || vs[0] != 1 || vs[1] != 2 {
|
||||
t.Errorf("expected in order traversal")
|
||||
}
|
||||
}
|
306
vendor/github.com/golang-collections/collections/tst/tst.go
generated
vendored
Normal file
306
vendor/github.com/golang-collections/collections/tst/tst.go
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
package tst
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
Node struct {
|
||||
key byte
|
||||
value interface{}
|
||||
left, middle, right *Node
|
||||
}
|
||||
NodeIterator struct {
|
||||
step int
|
||||
node *Node
|
||||
prev *NodeIterator
|
||||
}
|
||||
TernarySearchTree struct {
|
||||
length int
|
||||
root *Node
|
||||
}
|
||||
)
|
||||
|
||||
// Create a new ternary search tree
|
||||
func New() *TernarySearchTree {
|
||||
tree := &TernarySearchTree{}
|
||||
tree.Init()
|
||||
return tree
|
||||
}
|
||||
// Iterate over the collection
|
||||
func (this *TernarySearchTree) Do(callback func(string, interface{})bool) {
|
||||
if this.Len() == 0 {
|
||||
return
|
||||
}
|
||||
bs := []byte{}
|
||||
i := &NodeIterator{0,this.root,nil}
|
||||
for i != nil {
|
||||
switch i.step {
|
||||
// Left
|
||||
case 0:
|
||||
i.step++
|
||||
if i.node.left != nil {
|
||||
i = &NodeIterator{0,i.node.left,i}
|
||||
continue
|
||||
}
|
||||
// Value
|
||||
case 1:
|
||||
i.step++
|
||||
if i.node.key > 0 {
|
||||
bs = append(bs, i.node.key)
|
||||
}
|
||||
if i.node.value != nil {
|
||||
if !callback(string(bs), i.node.value) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Middle
|
||||
case 2:
|
||||
i.step++
|
||||
if i.node.middle != nil {
|
||||
i = &NodeIterator{0,i.node.middle,i}
|
||||
continue
|
||||
}
|
||||
// Right
|
||||
case 3:
|
||||
if len(bs) > 0 {
|
||||
bs = bs[:len(bs)-1]
|
||||
}
|
||||
i.step++
|
||||
if i.node.right != nil {
|
||||
i = &NodeIterator{0,i.node.right,i}
|
||||
continue
|
||||
}
|
||||
// Backtrack
|
||||
case 4:
|
||||
i = i.prev
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get the value at the specified key. Returns nil if not found.
|
||||
func (this *TernarySearchTree) Get(key string) interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
node := this.root
|
||||
bs := []byte(key)
|
||||
for i := 0; i < len(bs); {
|
||||
b := bs[i]
|
||||
if b > node.key {
|
||||
if node.right == nil {
|
||||
return nil
|
||||
}
|
||||
node = node.right
|
||||
} else if (b < node.key) {
|
||||
if node.left == nil {
|
||||
return nil
|
||||
}
|
||||
node = node.left
|
||||
} else {
|
||||
i++
|
||||
if i < len(bs) {
|
||||
if node.middle == nil {
|
||||
return nil
|
||||
}
|
||||
node = node.middle
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return node.value
|
||||
}
|
||||
func (this *TernarySearchTree) GetLongestPrefix(key string) interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := this.root
|
||||
v := n.value
|
||||
bs := []byte(key)
|
||||
for i := 0; i < len(bs); {
|
||||
b := bs[i]
|
||||
if n.value != nil {
|
||||
v = n.value
|
||||
}
|
||||
if b > n.key {
|
||||
if n.right == nil {
|
||||
break
|
||||
}
|
||||
n = n.right
|
||||
} else if b < n.key {
|
||||
if n.left == nil {
|
||||
break
|
||||
}
|
||||
n = n.left
|
||||
} else {
|
||||
i++
|
||||
if i < len(bs) {
|
||||
if n.middle == nil {
|
||||
break
|
||||
}
|
||||
n = n.middle
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if n.value != nil {
|
||||
v = n.value
|
||||
}
|
||||
return v
|
||||
}
|
||||
// Test to see whether or not the given key is contained in the tree.
|
||||
func (this *TernarySearchTree) Has(key string) bool {
|
||||
return this.Get(key) != nil
|
||||
}
|
||||
// Initialize the tree (reset it so that it's empty). New will do this for you.
|
||||
func (this *TernarySearchTree) Init() {
|
||||
this.length = 0
|
||||
this.root = nil
|
||||
}
|
||||
// Insert a new key value pair into the collection
|
||||
func (this *TernarySearchTree) Insert(key string, value interface{}) {
|
||||
// If the value is nil then remove this key from the collection
|
||||
if value == nil {
|
||||
this.Remove(key)
|
||||
return
|
||||
}
|
||||
|
||||
if this.length == 0 {
|
||||
this.root = &Node{0,nil,nil,nil,nil}
|
||||
}
|
||||
|
||||
t := this.root
|
||||
bs := []byte(key)
|
||||
for i := 0; i < len(bs); {
|
||||
b := bs[i]
|
||||
if b > t.key {
|
||||
if t.right == nil {
|
||||
t.right = &Node{b,nil,nil,nil,nil}
|
||||
}
|
||||
t = t.right
|
||||
} else if b < t.key {
|
||||
if t.left == nil {
|
||||
t.left = &Node{b,nil,nil,nil,nil}
|
||||
}
|
||||
t = t.left
|
||||
} else {
|
||||
i++
|
||||
if i < len(bs) {
|
||||
if t.middle == nil {
|
||||
t.middle = &Node{bs[i],nil,nil,nil,nil}
|
||||
}
|
||||
t = t.middle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if t.value == nil {
|
||||
this.length++
|
||||
}
|
||||
t.value = value
|
||||
}
|
||||
// Get the number of items stored in the tree
|
||||
func (this *TernarySearchTree) Len() int {
|
||||
return this.length
|
||||
}
|
||||
// Remove a key from the collection
|
||||
func (this *TernarySearchTree) Remove(key string) interface{} {
|
||||
if this.length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var remove *Node
|
||||
var direction int
|
||||
|
||||
t := this.root
|
||||
bs := []byte(key)
|
||||
for i := 0; i < len(bs); {
|
||||
b := bs[i]
|
||||
if b > t.key {
|
||||
// Not in the collection
|
||||
if t.right == nil {
|
||||
return nil
|
||||
}
|
||||
// This is a branch so we have to keep it
|
||||
remove = t
|
||||
direction = 1
|
||||
// Move to the next node
|
||||
t = t.right
|
||||
} else if b < t.key {
|
||||
// Not in the collection
|
||||
if t.left == nil {
|
||||
return nil
|
||||
}
|
||||
// This is a branch so we have to keep it
|
||||
remove = t
|
||||
direction = -1
|
||||
// Move to the next node
|
||||
t = t.left
|
||||
} else {
|
||||
i++
|
||||
if i < len(bs) {
|
||||
// Not in the collection
|
||||
if t.middle == nil {
|
||||
return nil
|
||||
}
|
||||
// Has a value so we need to keep at least this much
|
||||
if t.value != nil {
|
||||
remove = t
|
||||
direction = 0
|
||||
}
|
||||
// Move to the next node
|
||||
t = t.middle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this was the only item in the tree, set the root pointer to nil
|
||||
if this.length == 1 {
|
||||
this.root = nil
|
||||
} else {
|
||||
if direction == -1 {
|
||||
remove.left = nil
|
||||
} else if direction == 0 {
|
||||
remove.middle = nil
|
||||
} else {
|
||||
remove.right = nil
|
||||
}
|
||||
}
|
||||
this.length--
|
||||
return t.value
|
||||
}
|
||||
func (this *TernarySearchTree) String() string {
|
||||
if this.length == 0 {
|
||||
return "{}"
|
||||
}
|
||||
|
||||
return this.root.String()
|
||||
}
|
||||
// Dump the tree to a string for easier debugging
|
||||
func (this *Node) String() string {
|
||||
str := "{" + string(this.key)
|
||||
if this.value != nil {
|
||||
str += ":" + fmt.Sprint(this.value)
|
||||
}
|
||||
if this.left != nil {
|
||||
str += this.left.String()
|
||||
} else {
|
||||
str += " "
|
||||
}
|
||||
if this.middle != nil {
|
||||
str += this.middle.String()
|
||||
} else {
|
||||
str += " "
|
||||
}
|
||||
if this.right != nil {
|
||||
str += this.right.String()
|
||||
} else {
|
||||
str += " "
|
||||
}
|
||||
str += "}"
|
||||
return str
|
||||
}
|
83
vendor/github.com/golang-collections/collections/tst/tst_test.go
generated
vendored
Normal file
83
vendor/github.com/golang-collections/collections/tst/tst_test.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package tst
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func randomString() string {
|
||||
n := 3 + rand.Intn(10)
|
||||
bs := make([]byte, n)
|
||||
for i := 0; i<n; i++ {
|
||||
bs[i] = byte(97 + rand.Intn(25))
|
||||
}
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
func Test(t *testing.T) {
|
||||
tree := New()
|
||||
tree.Insert("test", 1)
|
||||
if tree.Len() != 1 {
|
||||
t.Errorf("expecting len 1")
|
||||
}
|
||||
if !tree.Has("test") {
|
||||
t.Errorf("expecting to find key=test")
|
||||
}
|
||||
|
||||
tree.Insert("testing", 2)
|
||||
tree.Insert("abcd", 0)
|
||||
|
||||
found := false
|
||||
tree.Do(func(key string, val interface{})bool {
|
||||
if key == "test" && val.(int) == 1 {
|
||||
found = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
if !found {
|
||||
t.Errorf("expecting iterator to find test")
|
||||
}
|
||||
|
||||
tree.Remove("testing")
|
||||
tree.Remove("abcd")
|
||||
|
||||
v := tree.Remove("test")
|
||||
if tree.Len() != 0 {
|
||||
t.Errorf("expecting len 0")
|
||||
}
|
||||
if tree.Has("test") {
|
||||
t.Errorf("expecting not to find key=test")
|
||||
}
|
||||
if v.(int) != 1 {
|
||||
t.Errorf("expecting value=1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsert(b *testing.B) {
|
||||
b.StopTimer()
|
||||
strs := make([]string, b.N)
|
||||
for i := 0; i<b.N; i++ {
|
||||
strs[i] = randomString()
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
tree := New()
|
||||
for i, str := range strs {
|
||||
tree.Insert(str, i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMapInsert(b *testing.B) {
|
||||
b.StopTimer()
|
||||
strs := make([]string, b.N)
|
||||
for i := 0; i<b.N; i++ {
|
||||
strs[i] = randomString()
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
m := make(map[string]int)
|
||||
for i, str := range strs {
|
||||
m[str] = i
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user