Switch from Godep to go vendoring
This commit is contained in:
parent
6b37713bc0
commit
cd317761c5
1504 changed files with 263076 additions and 34441 deletions
20
vendor/github.com/steveyen/gtreap/LICENSE
generated
vendored
Normal file
20
vendor/github.com/steveyen/gtreap/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
Copyright (C) 2012 Steve Yen
|
||||
|
||||
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.
|
90
vendor/github.com/steveyen/gtreap/README.md
generated
vendored
Normal file
90
vendor/github.com/steveyen/gtreap/README.md
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
gtreap
|
||||
------
|
||||
|
||||
gtreap is an immutable treap implementation in the Go Language
|
||||
|
||||
[](https://godoc.org/github.com/steveyen/gtreap) [](https://drone.io/github.com/steveyen/gtreap/latest) [](https://coveralls.io/r/steveyen/gtreap)
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
gtreap implements an immutable treap data structure in golang.
|
||||
|
||||
By treap, this data structure is both a heap and a binary search tree.
|
||||
|
||||
By immutable, any updates/deletes to a treap will return a new treap
|
||||
which can share internal nodes with the previous treap. All nodes in
|
||||
this implementation are read-only after their creation. This allows
|
||||
concurrent readers to operate safely with concurrent writers as
|
||||
modifications only create new data structures and never modify
|
||||
existing data structures. This is a simple approach to achieving MVCC
|
||||
or multi-version concurrency control.
|
||||
|
||||
By heap, items in the treap follow the heap-priority property, where a
|
||||
parent node will have higher priority than its left and right children
|
||||
nodes.
|
||||
|
||||
By binary search tree, items are store lexigraphically, ordered by a
|
||||
user-supplied Compare function.
|
||||
|
||||
To get a probabilistic O(lg N) tree height, you should use a random
|
||||
priority number during the Upsert() operation.
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
MIT
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"github.com/steveyen/gtreap"
|
||||
)
|
||||
|
||||
func stringCompare(a, b interface{}) int {
|
||||
return bytes.Compare([]byte(a.(string)), []byte(b.(string)))
|
||||
}
|
||||
|
||||
t := gtreap.NewTreap(stringCompare)
|
||||
t = t.Upsert("hi", rand.Int())
|
||||
t = t.Upsert("hola", rand.Int())
|
||||
t = t.Upsert("bye", rand.Int())
|
||||
t = t.Upsert("adios", rand.Int())
|
||||
|
||||
hi = t.Get("hi")
|
||||
bye = t.Get("bye")
|
||||
|
||||
// Some example Delete()'s...
|
||||
t = t.Delete("bye")
|
||||
nilValueHere = t.Get("bye")
|
||||
t2 = t.Delete("hi")
|
||||
nilValueHere2 = t2.Get("hi")
|
||||
|
||||
// Since we still hold onto treap t, we can still access "hi".
|
||||
hiStillExistsInTreapT = t.Get("hi")
|
||||
|
||||
t.VisitAscend("cya", func(i Item) bool {
|
||||
// This visitor callback will be invoked with every item
|
||||
// from "cya" onwards. So: "hi", "hola".
|
||||
// If we want to stop visiting, return false;
|
||||
// otherwise a true return result means keep visiting items.
|
||||
return true
|
||||
})
|
||||
|
||||
Tips
|
||||
====
|
||||
|
||||
The Upsert() method takes both an Item (an interface{}) and a heap
|
||||
priority. Usually, that priority should be a random int
|
||||
(math/rand.Int()) or perhaps even a hash of the item. However, if you
|
||||
want to shuffle more commonly accessed items nearer to the top of the
|
||||
treap for faster access, at the potential cost of not approaching a
|
||||
probabilistic O(lg N) tree height, then you might tweak the priority.
|
||||
|
||||
See also
|
||||
========
|
||||
|
||||
For a simple, ordered, key-value storage or persistence library built
|
||||
on immutable treaps, see: https://github.com/steveyen/gkvlite
|
188
vendor/github.com/steveyen/gtreap/treap.go
generated
vendored
Normal file
188
vendor/github.com/steveyen/gtreap/treap.go
generated
vendored
Normal file
|
@ -0,0 +1,188 @@
|
|||
package gtreap
|
||||
|
||||
type Treap struct {
|
||||
compare Compare
|
||||
root *node
|
||||
}
|
||||
|
||||
// Compare returns an integer comparing the two items
|
||||
// lexicographically. The result will be 0 if a==b, -1 if a < b, and
|
||||
// +1 if a > b.
|
||||
type Compare func(a, b interface{}) int
|
||||
|
||||
// Item can be anything.
|
||||
type Item interface{}
|
||||
|
||||
type node struct {
|
||||
item Item
|
||||
priority int
|
||||
left *node
|
||||
right *node
|
||||
}
|
||||
|
||||
func NewTreap(c Compare) *Treap {
|
||||
return &Treap{compare: c, root: nil}
|
||||
}
|
||||
|
||||
func (t *Treap) Min() Item {
|
||||
n := t.root
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
for n.left != nil {
|
||||
n = n.left
|
||||
}
|
||||
return n.item
|
||||
}
|
||||
|
||||
func (t *Treap) Max() Item {
|
||||
n := t.root
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
for n.right != nil {
|
||||
n = n.right
|
||||
}
|
||||
return n.item
|
||||
}
|
||||
|
||||
func (t *Treap) Get(target Item) Item {
|
||||
n := t.root
|
||||
for n != nil {
|
||||
c := t.compare(target, n.item)
|
||||
if c < 0 {
|
||||
n = n.left
|
||||
} else if c > 0 {
|
||||
n = n.right
|
||||
} else {
|
||||
return n.item
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note: only the priority of the first insert of an item is used.
|
||||
// Priorities from future updates on already existing items are
|
||||
// ignored. To change the priority for an item, you need to do a
|
||||
// Delete then an Upsert.
|
||||
func (t *Treap) Upsert(item Item, itemPriority int) *Treap {
|
||||
r := t.union(t.root, &node{item: item, priority: itemPriority})
|
||||
return &Treap{compare: t.compare, root: r}
|
||||
}
|
||||
|
||||
func (t *Treap) union(this *node, that *node) *node {
|
||||
if this == nil {
|
||||
return that
|
||||
}
|
||||
if that == nil {
|
||||
return this
|
||||
}
|
||||
if this.priority > that.priority {
|
||||
left, middle, right := t.split(that, this.item)
|
||||
if middle == nil {
|
||||
return &node{
|
||||
item: this.item,
|
||||
priority: this.priority,
|
||||
left: t.union(this.left, left),
|
||||
right: t.union(this.right, right),
|
||||
}
|
||||
}
|
||||
return &node{
|
||||
item: middle.item,
|
||||
priority: this.priority,
|
||||
left: t.union(this.left, left),
|
||||
right: t.union(this.right, right),
|
||||
}
|
||||
}
|
||||
// We don't use middle because the "that" has precendence.
|
||||
left, _, right := t.split(this, that.item)
|
||||
return &node{
|
||||
item: that.item,
|
||||
priority: that.priority,
|
||||
left: t.union(left, that.left),
|
||||
right: t.union(right, that.right),
|
||||
}
|
||||
}
|
||||
|
||||
// Splits a treap into two treaps based on a split item "s".
|
||||
// The result tuple-3 means (left, X, right), where X is either...
|
||||
// nil - meaning the item s was not in the original treap.
|
||||
// non-nil - returning the node that had item s.
|
||||
// The tuple-3's left result treap has items < s,
|
||||
// and the tuple-3's right result treap has items > s.
|
||||
func (t *Treap) split(n *node, s Item) (*node, *node, *node) {
|
||||
if n == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
c := t.compare(s, n.item)
|
||||
if c == 0 {
|
||||
return n.left, n, n.right
|
||||
}
|
||||
if c < 0 {
|
||||
left, middle, right := t.split(n.left, s)
|
||||
return left, middle, &node{
|
||||
item: n.item,
|
||||
priority: n.priority,
|
||||
left: right,
|
||||
right: n.right,
|
||||
}
|
||||
}
|
||||
left, middle, right := t.split(n.right, s)
|
||||
return &node{
|
||||
item: n.item,
|
||||
priority: n.priority,
|
||||
left: n.left,
|
||||
right: left,
|
||||
}, middle, right
|
||||
}
|
||||
|
||||
func (t *Treap) Delete(target Item) *Treap {
|
||||
left, _, right := t.split(t.root, target)
|
||||
return &Treap{compare: t.compare, root: t.join(left, right)}
|
||||
}
|
||||
|
||||
// All the items from this are < items from that.
|
||||
func (t *Treap) join(this *node, that *node) *node {
|
||||
if this == nil {
|
||||
return that
|
||||
}
|
||||
if that == nil {
|
||||
return this
|
||||
}
|
||||
if this.priority > that.priority {
|
||||
return &node{
|
||||
item: this.item,
|
||||
priority: this.priority,
|
||||
left: this.left,
|
||||
right: t.join(this.right, that),
|
||||
}
|
||||
}
|
||||
return &node{
|
||||
item: that.item,
|
||||
priority: that.priority,
|
||||
left: t.join(this, that.left),
|
||||
right: that.right,
|
||||
}
|
||||
}
|
||||
|
||||
type ItemVisitor func(i Item) bool
|
||||
|
||||
// Visit items greater-than-or-equal to the pivot.
|
||||
func (t *Treap) VisitAscend(pivot Item, visitor ItemVisitor) {
|
||||
t.visitAscend(t.root, pivot, visitor)
|
||||
}
|
||||
|
||||
func (t *Treap) visitAscend(n *node, pivot Item, visitor ItemVisitor) bool {
|
||||
if n == nil {
|
||||
return true
|
||||
}
|
||||
if t.compare(pivot, n.item) <= 0 {
|
||||
if !t.visitAscend(n.left, pivot, visitor) {
|
||||
return false
|
||||
}
|
||||
if !visitor(n.item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return t.visitAscend(n.right, pivot, visitor)
|
||||
}
|
259
vendor/github.com/steveyen/gtreap/treap_test.go
generated
vendored
Normal file
259
vendor/github.com/steveyen/gtreap/treap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,259 @@
|
|||
package gtreap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func stringCompare(a, b interface{}) int {
|
||||
return bytes.Compare([]byte(a.(string)), []byte(b.(string)))
|
||||
}
|
||||
|
||||
func TestTreap(t *testing.T) {
|
||||
x := NewTreap(stringCompare)
|
||||
if x == nil {
|
||||
t.Errorf("expected NewTreap to work")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
op string
|
||||
val string
|
||||
pri int
|
||||
exp string
|
||||
}{
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"ups", "a", 100, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"ups", "b", 200, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"get", "b", -1, "b"},
|
||||
{"ups", "c", 300, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"get", "b", -1, "b"},
|
||||
{"get", "c", -1, "c"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"ups", "a", 400, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"get", "b", -1, "b"},
|
||||
{"get", "c", -1, "c"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"del", "a", -1, ""},
|
||||
{"get", "a", -1, "NIL"},
|
||||
{"get", "b", -1, "b"},
|
||||
{"get", "c", -1, "c"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"ups", "a", 10, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"get", "b", -1, "b"},
|
||||
{"get", "c", -1, "c"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"del", "a", -1, ""},
|
||||
{"del", "b", -1, ""},
|
||||
{"del", "c", -1, ""},
|
||||
{"get", "a", -1, "NIL"},
|
||||
{"get", "b", -1, "NIL"},
|
||||
{"get", "c", -1, "NIL"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"del", "a", -1, ""},
|
||||
{"del", "b", -1, ""},
|
||||
{"del", "c", -1, ""},
|
||||
{"get", "a", -1, "NIL"},
|
||||
{"get", "b", -1, "NIL"},
|
||||
{"get", "c", -1, "NIL"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"ups", "a", 10, ""},
|
||||
{"get", "a", -1, "a"},
|
||||
{"get", "b", -1, "NIL"},
|
||||
{"get", "c", -1, "NIL"},
|
||||
{"get", "not-there", -1, "NIL"},
|
||||
{"ups", "b", 1000, "b"},
|
||||
{"del", "b", -1, ""}, // cover join that is nil
|
||||
{"ups", "b", 20, "b"},
|
||||
{"ups", "c", 12, "c"},
|
||||
{"del", "b", -1, ""}, // cover join second return
|
||||
{"ups", "a", 5, "a"}, // cover upsert existing with lower priority
|
||||
}
|
||||
|
||||
for testIdx, test := range tests {
|
||||
switch test.op {
|
||||
case "get":
|
||||
i := x.Get(test.val)
|
||||
if i != test.exp && !(i == nil && test.exp == "NIL") {
|
||||
t.Errorf("test: %v, on Get, expected: %v, got: %v", testIdx, test.exp, i)
|
||||
}
|
||||
case "ups":
|
||||
x = x.Upsert(test.val, test.pri)
|
||||
case "del":
|
||||
x = x.Delete(test.val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func load(x *Treap, arr []string) *Treap {
|
||||
for i, s := range arr {
|
||||
x = x.Upsert(s, i)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func visitExpect(t *testing.T, x *Treap, start string, arr []string) {
|
||||
n := 0
|
||||
x.VisitAscend(start, func(i Item) bool {
|
||||
if i.(string) != arr[n] {
|
||||
t.Errorf("expected visit item: %v, saw: %v", arr[n], i)
|
||||
}
|
||||
n++
|
||||
return true
|
||||
})
|
||||
if n != len(arr) {
|
||||
t.Errorf("expected # visit callbacks: %v, saw: %v", len(arr), n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVisit(t *testing.T) {
|
||||
x := NewTreap(stringCompare)
|
||||
visitExpect(t, x, "a", []string{})
|
||||
|
||||
x = load(x, []string{"e", "d", "c", "c", "a", "b", "a"})
|
||||
|
||||
visitX := func() {
|
||||
visitExpect(t, x, "a", []string{"a", "b", "c", "d", "e"})
|
||||
visitExpect(t, x, "a1", []string{"b", "c", "d", "e"})
|
||||
visitExpect(t, x, "b", []string{"b", "c", "d", "e"})
|
||||
visitExpect(t, x, "b1", []string{"c", "d", "e"})
|
||||
visitExpect(t, x, "c", []string{"c", "d", "e"})
|
||||
visitExpect(t, x, "c1", []string{"d", "e"})
|
||||
visitExpect(t, x, "d", []string{"d", "e"})
|
||||
visitExpect(t, x, "d1", []string{"e"})
|
||||
visitExpect(t, x, "e", []string{"e"})
|
||||
visitExpect(t, x, "f", []string{})
|
||||
}
|
||||
visitX()
|
||||
|
||||
var y *Treap
|
||||
y = x.Upsert("f", 1)
|
||||
y = y.Delete("a")
|
||||
y = y.Upsert("cc", 2)
|
||||
y = y.Delete("c")
|
||||
|
||||
visitExpect(t, y, "a", []string{"b", "cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "a1", []string{"b", "cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "b", []string{"b", "cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "b1", []string{"cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "c", []string{"cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "c1", []string{"cc", "d", "e", "f"})
|
||||
visitExpect(t, y, "d", []string{"d", "e", "f"})
|
||||
visitExpect(t, y, "d1", []string{"e", "f"})
|
||||
visitExpect(t, y, "e", []string{"e", "f"})
|
||||
visitExpect(t, y, "f", []string{"f"})
|
||||
visitExpect(t, y, "z", []string{})
|
||||
|
||||
// an uninitialized treap
|
||||
z := NewTreap(stringCompare)
|
||||
|
||||
// a treap to force left traversal of min
|
||||
lmt := NewTreap(stringCompare)
|
||||
lmt = lmt.Upsert("b", 2)
|
||||
lmt = lmt.Upsert("a", 1)
|
||||
|
||||
// The x treap should be unchanged.
|
||||
visitX()
|
||||
|
||||
if x.Min() != "a" {
|
||||
t.Errorf("expected min of a")
|
||||
}
|
||||
if x.Max() != "e" {
|
||||
t.Errorf("expected max of d")
|
||||
}
|
||||
if y.Min() != "b" {
|
||||
t.Errorf("expected min of b")
|
||||
}
|
||||
if y.Max() != "f" {
|
||||
t.Errorf("expected max of f")
|
||||
}
|
||||
if z.Min() != nil {
|
||||
t.Errorf("expected min of nil")
|
||||
}
|
||||
if z.Max() != nil {
|
||||
t.Error("expected max of nil")
|
||||
}
|
||||
if lmt.Min() != "a" {
|
||||
t.Errorf("expected min of a")
|
||||
}
|
||||
if lmt.Max() != "b" {
|
||||
t.Errorf("expeced max of b")
|
||||
}
|
||||
}
|
||||
|
||||
func visitExpectEndAtC(t *testing.T, x *Treap, start string, arr []string) {
|
||||
n := 0
|
||||
x.VisitAscend(start, func(i Item) bool {
|
||||
if stringCompare(i, "c") > 0 {
|
||||
return false
|
||||
}
|
||||
if i.(string) != arr[n] {
|
||||
t.Errorf("expected visit item: %v, saw: %v", arr[n], i)
|
||||
}
|
||||
n++
|
||||
return true
|
||||
})
|
||||
if n != len(arr) {
|
||||
t.Errorf("expected # visit callbacks: %v, saw: %v", len(arr), n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVisitEndEarly(t *testing.T) {
|
||||
x := NewTreap(stringCompare)
|
||||
visitExpectEndAtC(t, x, "a", []string{})
|
||||
|
||||
x = load(x, []string{"e", "d", "c", "c", "a", "b", "a", "e"})
|
||||
|
||||
visitX := func() {
|
||||
visitExpectEndAtC(t, x, "a", []string{"a", "b", "c"})
|
||||
visitExpectEndAtC(t, x, "a1", []string{"b", "c"})
|
||||
visitExpectEndAtC(t, x, "b", []string{"b", "c"})
|
||||
visitExpectEndAtC(t, x, "b1", []string{"c"})
|
||||
visitExpectEndAtC(t, x, "c", []string{"c"})
|
||||
visitExpectEndAtC(t, x, "c1", []string{})
|
||||
visitExpectEndAtC(t, x, "d", []string{})
|
||||
visitExpectEndAtC(t, x, "d1", []string{})
|
||||
visitExpectEndAtC(t, x, "e", []string{})
|
||||
visitExpectEndAtC(t, x, "f", []string{})
|
||||
}
|
||||
visitX()
|
||||
}
|
||||
|
||||
func TestPriorityAfterUpsert(t *testing.T) {
|
||||
// See https://github.com/steveyen/gtreap/issues/3 found by icexin.
|
||||
|
||||
var check func(n *node, level int, expectedPriority map[string]int)
|
||||
check = func(n *node, level int, expectedPriority map[string]int) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.priority != expectedPriority[n.item.(string)] {
|
||||
t.Errorf("wrong priority")
|
||||
}
|
||||
check(n.left, level+1, expectedPriority)
|
||||
check(n.right, level+1, expectedPriority)
|
||||
}
|
||||
|
||||
s := NewTreap(stringCompare)
|
||||
s = s.Upsert("m", 20)
|
||||
s = s.Upsert("l", 18)
|
||||
s = s.Upsert("n", 19)
|
||||
|
||||
check(s.root, 0, map[string]int{
|
||||
"m": 20,
|
||||
"l": 18,
|
||||
"n": 19,
|
||||
})
|
||||
|
||||
s = s.Upsert("m", 4)
|
||||
|
||||
check(s.root, 0, map[string]int{
|
||||
"m": 20,
|
||||
"l": 18,
|
||||
"n": 19,
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue