mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 23:19:58 +00:00
TUN-528: Move cloudflared into a separate repo
This commit is contained in:
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")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user