Update deps

This commit is contained in:
Frank Denis 2018-04-07 17:14:53 +02:00
parent 10986aba62
commit a4366b0593
15 changed files with 1592 additions and 15 deletions

16
Gopkg.lock generated
View File

@ -92,7 +92,7 @@
branch = "master"
name = "github.com/jedisct1/dlog"
packages = ["."]
revision = "52c32ac39e436cd9295a4629a91f0613ce67052f"
revision = "d3f1bf94f2a248f6d000c48612836796f333f2dd"
[[projects]]
branch = "master"
@ -112,6 +112,12 @@
packages = ["."]
revision = "88b1956e8d9a013c98dda528d3a5b77f168b057f"
[[projects]]
name = "github.com/k-sone/critbitgo"
packages = ["."]
revision = "1b44ffc7fc9ad8dea28251e340eadb04093c8af3"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/kardianos/osext"
@ -142,7 +148,7 @@
"poly1305",
"salsa20/salsa"
]
revision = "12892e8c234f4fe6f6803f052061de9057903bb2"
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
[[projects]]
branch = "master"
@ -154,7 +160,7 @@
"ipv4",
"ipv6"
]
revision = "b68f30494add4df6bd8ef5e82803f308e7f7c59c"
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
[[projects]]
branch = "master"
@ -166,7 +172,7 @@
"windows/svc/eventlog",
"windows/svc/mgr"
]
revision = "378d26f46672a356c46195c28f61bdb4c0a781dd"
revision = "3b87a42e500a6dc65dae1a55d0b641295971163e"
[[projects]]
name = "gopkg.in/natefinch/lumberjack.v2"
@ -177,6 +183,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "b42eaffe36e3d325de06319d842b067e1c2b9f197089422d6a2df2a5947e3c4c"
inputs-digest = "a4dd651828c61eaf4a60761a081ef914190ece4cfa682cb3391712be98bdb34b"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -38,6 +38,10 @@
branch = "master"
name = "github.com/jedisct1/dlog"
[[constraint]]
branch = "master"
name = "github.com/jedisct1/go-clocksmith"
[[constraint]]
branch = "master"
name = "github.com/jedisct1/go-minisign"
@ -46,17 +50,17 @@
branch = "master"
name = "github.com/jedisct1/xsecretbox"
[[constraint]]
name = "github.com/k-sone/critbitgo"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/kardianos/service"
[[constraint]]
name = "github.com/miekg/dns"
version = "1.0.4"
[[constraint]]
branch = "master"
name = "github.com/pquerna/cachecontrol"
version = "1.0.5"
[[constraint]]
branch = "master"
@ -65,7 +69,3 @@
[[constraint]]
name = "gopkg.in/natefinch/lumberjack.v2"
version = "2.1.0"
[[constraint]]
branch = "master"
name = "github.com/jedisct1/go-clocksmith"

View File

@ -15,7 +15,7 @@
"windows/registry",
"windows/svc/eventlog"
]
revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd"
revision = "378d26f46672a356c46195c28f61bdb4c0a781dd"
[solve-meta]
analyzer-name = "dep"

6
vendor/github.com/k-sone/critbitgo/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,6 @@
language: go
go:
- 1.5
- 1.6
- 1.7

7
vendor/github.com/k-sone/critbitgo/CHANGES.md generated vendored Normal file
View File

@ -0,0 +1,7 @@
## 1.1.0 (2016/12/29)
- Add `LongestPrefix ` and `Walk` functions
## 1.0.0 (2016/04/02)
- Initial release

22
vendor/github.com/k-sone/critbitgo/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Keita Sone
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.

44
vendor/github.com/k-sone/critbitgo/README.md generated vendored Normal file
View File

@ -0,0 +1,44 @@
[![Build Status](https://travis-ci.org/k-sone/critbitgo.svg?branch=master)](https://travis-ci.org/k-sone/critbitgo)
critbitgo
=========
[Crit-bit trees](http://cr.yp.to/critbit.html) in golang and its applications.
This implementation extended to handle the key that contains a null character from [C implementation](https://github.com/agl/critbit).
Usage
--------
```go
// Create Trie
trie := critbitgo.NewTrie()
// Insert
trie.Insert([]byte("aa"), "value1")
trie.Insert([]byte("bb"), "value2")
trie.Insert([]byte("ab"), "value3")
// Get
v, ok := trie.Get([]byte("aa"))
fmt.Println(v, ok) // -> value1 true
// Iterate containing keys
trie.Allprefixed([]byte{}, func(key []byte, value interface{}) bool {
fmt.Println(key, value) // -> [97 97] value1
// [97 98] value3
// [98 98] value2
return true
})
// Delete
v, ok = trie.Delete([]byte("aa"))
fmt.Println(v, ok) // -> value1 true
v, ok = trie.Delete([]byte("aa"))
fmt.Println(v, ok) // -> <nil> false
```
License
-------
MIT

388
vendor/github.com/k-sone/critbitgo/critbit.go generated vendored Normal file
View File

@ -0,0 +1,388 @@
package critbitgo
import (
"bytes"
"encoding/hex"
"fmt"
"io"
"os"
"strconv"
)
// The matrix of most significant bit
var msbMatrix [256]byte
func buildMsbMatrix() {
for i := 0; i < len(msbMatrix); i++ {
b := byte(i)
b |= b >> 1
b |= b >> 2
b |= b >> 4
msbMatrix[i] = b &^ (b >> 1)
}
}
type node struct {
internal *internal
external *external
}
type internal struct {
child [2]node
offset int
bit byte
cont bool // if true, key of child[1] contains key of child[0]
}
type external struct {
key []byte
value interface{}
}
// finding the critical bit.
func (n *external) criticalBit(key []byte) (offset int, bit byte, cont bool) {
nlen := len(n.key)
klen := len(key)
mlen := nlen
if nlen > klen {
mlen = klen
}
// find first differing byte and bit
for offset = 0; offset < mlen; offset++ {
if a, b := key[offset], n.key[offset]; a != b {
bit = msbMatrix[a^b]
return
}
}
if nlen < klen {
bit = msbMatrix[key[offset]]
} else if nlen > klen {
bit = msbMatrix[n.key[offset]]
} else {
// two keys are equal
offset = -1
}
return offset, bit, true
}
// calculate direction.
func (n *internal) direction(key []byte) int {
if n.offset < len(key) && (key[n.offset]&n.bit != 0 || n.cont) {
return 1
}
return 0
}
// Crit-bit Tree
type Trie struct {
root node
size int
}
// searching the tree.
func (t *Trie) search(key []byte) *node {
n := &t.root
for n.internal != nil {
n = &n.internal.child[n.internal.direction(key)]
}
return n
}
// membership testing.
func (t *Trie) Contains(key []byte) bool {
if n := t.search(key); n.external != nil && bytes.Equal(n.external.key, key) {
return true
}
return false
}
// get member.
// if `key` is in Trie, `ok` is true.
func (t *Trie) Get(key []byte) (value interface{}, ok bool) {
if n := t.search(key); n.external != nil && bytes.Equal(n.external.key, key) {
return n.external.value, true
}
return
}
// insert into the tree (replaceable).
func (t *Trie) insert(key []byte, value interface{}, replace bool) bool {
// an empty tree
if t.size == 0 {
t.root.external = &external{
key: key,
value: value,
}
t.size = 1
return true
}
n := t.search(key)
newOffset, newBit, newCont := n.external.criticalBit(key)
// already exists in the tree
if newOffset == -1 {
if replace {
n.external.value = value
return true
}
return false
}
// allocate new node
newNode := &internal{
offset: newOffset,
bit: newBit,
cont: newCont,
}
direction := newNode.direction(key)
newNode.child[direction].external = &external{
key: key,
value: value,
}
// insert new node
wherep := &t.root
for in := wherep.internal; in != nil; in = wherep.internal {
if in.offset > newOffset || (in.offset == newOffset && in.bit < newBit) {
break
}
wherep = &in.child[in.direction(key)]
}
if wherep.internal != nil {
newNode.child[1-direction].internal = wherep.internal
} else {
newNode.child[1-direction].external = wherep.external
wherep.external = nil
}
wherep.internal = newNode
t.size += 1
return true
}
// insert into the tree.
// if `key` is alredy in Trie, return false.
func (t *Trie) Insert(key []byte, value interface{}) bool {
return t.insert(key, value, false)
}
// set into the tree.
func (t *Trie) Set(key []byte, value interface{}) {
t.insert(key, value, true)
}
// deleting elements.
// if `key` is in Trie, `ok` is true.
func (t *Trie) Delete(key []byte) (value interface{}, ok bool) {
// an empty tree
if t.size == 0 {
return
}
var direction int
var whereq *node // pointer to the grandparent
var wherep *node = &t.root
// finding the best candidate to delete
for in := wherep.internal; in != nil; in = wherep.internal {
direction = in.direction(key)
whereq = wherep
wherep = &in.child[direction]
}
// checking that we have the right element
if !bytes.Equal(wherep.external.key, key) {
return
}
value = wherep.external.value
ok = true
// removing the node
if whereq == nil {
wherep.external = nil
} else {
othern := whereq.internal.child[1-direction]
whereq.internal = othern.internal
whereq.external = othern.external
}
t.size -= 1
return
}
// clearing a tree.
func (t *Trie) Clear() {
t.root.internal = nil
t.root.external = nil
t.size = 0
}
// return the number of key in a tree.
func (t *Trie) Size() int {
return t.size
}
// fetching elements with a given prefix.
// handle is called with arguments key and value (if handle returns `false`, the iteration is aborted)
func (t *Trie) Allprefixed(prefix []byte, handle func(key []byte, value interface{}) bool) bool {
// an empty tree
if t.size == 0 {
return true
}
// walk tree, maintaining top pointer
p := &t.root
top := p
if len(prefix) > 0 {
for p.internal != nil {
top = p
p = &p.internal.child[p.internal.direction(prefix)]
}
// check prefix
if !bytes.Contains(p.external.key, prefix) {
return true
}
}
return allprefixed(top, handle)
}
func allprefixed(n *node, handle func([]byte, interface{}) bool) bool {
if n.internal != nil {
// dealing with an internal node while recursing
for i := 0; i < 2; i++ {
if !allprefixed(&n.internal.child[i], handle) {
return false
}
}
} else {
// dealing with an external node while recursing
return handle(n.external.key, n.external.value)
}
return true
}
// Search for the longest matching key from the beginning of the given key.
// if `key` is in Trie, `ok` is true.
func (t *Trie) LongestPrefix(given []byte) (key []byte, value interface{}, ok bool) {
// an empty tree
if t.size == 0 {
return
}
return longestPrefix(&t.root, given)
}
func longestPrefix(n *node, key []byte) ([]byte, interface{}, bool) {
if n.internal != nil {
direction := n.internal.direction(key)
if k, v, ok := longestPrefix(&n.internal.child[direction], key); ok {
return k, v, ok
}
if direction == 1 {
return longestPrefix(&n.internal.child[0], key)
}
} else {
if bytes.HasPrefix(key, n.external.key) {
return n.external.key, n.external.value, true
}
}
return nil, nil, false
}
// Iterating elements from a given start key.
// handle is called with arguments key and value (if handle returns `false`, the iteration is aborted)
func (t *Trie) Walk(start []byte, handle func(key []byte, value interface{}) bool) bool {
var seek bool
if start != nil {
seek = true
}
return walk(&t.root, start, &seek, handle)
}
func walk(n *node, key []byte, seek *bool, handle func([]byte, interface{}) bool) bool {
if n.internal != nil {
var direction int
if *seek {
direction = n.internal.direction(key)
}
if !walk(&n.internal.child[direction], key, seek, handle) {
return false
}
if !(*seek) && direction == 0 {
// iteration another side
return walk(&n.internal.child[1], key, seek, handle)
}
return true
} else {
if *seek {
if bytes.Equal(n.external.key, key) {
// seek completed
*seek = false
} else {
// key is not in Trie
return false
}
}
return handle(n.external.key, n.external.value)
}
}
// dump tree. (for debugging)
func (t *Trie) Dump(w io.Writer) {
if t.root.internal == nil && t.root.external == nil {
return
}
if w == nil {
w = os.Stdout
}
dump(w, &t.root, true, "")
}
func dump(w io.Writer, n *node, right bool, prefix string) {
var ownprefix string
if right {
ownprefix = prefix
} else {
ownprefix = prefix[:len(prefix)-1] + "`"
}
if in := n.internal; in != nil {
fmt.Fprintf(w, "%s-- off=%d, bit=%08b(%02x), cont=%v\n", ownprefix, in.offset, in.bit, in.bit, in.cont)
for i := 0; i < 2; i++ {
var nextprefix string
switch i {
case 0:
nextprefix = prefix + " |"
right = true
case 1:
nextprefix = prefix + " "
right = false
}
dump(w, &in.child[i], right, nextprefix)
}
} else {
fmt.Fprintf(w, "%s-- key=%d (%s)\n", ownprefix, n.external.key, key2str(n.external.key))
}
return
}
func key2str(key []byte) string {
for _, c := range key {
if !strconv.IsPrint(rune(c)) {
return hex.EncodeToString(key)
}
}
return string(key)
}
// create a tree.
func NewTrie() *Trie {
return &Trie{}
}
func init() {
buildMsbMatrix()
}

348
vendor/github.com/k-sone/critbitgo/critbit_test.go generated vendored Normal file
View File

@ -0,0 +1,348 @@
package critbitgo_test
import (
"bytes"
"math/rand"
"testing"
"github.com/k-sone/critbitgo"
)
func buildTrie(t *testing.T, keys []string) *critbitgo.Trie {
trie := critbitgo.NewTrie()
for _, key := range keys {
if !trie.Insert([]byte(key), key) {
t.Errorf("Insert() - failed insert \"%s\"\n%s", key, dumpTrie(trie))
}
}
return trie
}
func dumpTrie(trie *critbitgo.Trie) string {
buf := bytes.NewBufferString("")
trie.Dump(buf)
return buf.String()
}
func TestInsert(t *testing.T) {
// normal build
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
dump := dumpTrie(trie)
// random build
random := rand.New(rand.NewSource(0))
for i := 0; i < 10; i++ {
// shuffle keys
lkeys := make([]string, len(keys))
for j, index := range random.Perm(len(keys)) {
lkeys[j] = keys[index]
}
ltrie := buildTrie(t, lkeys)
ldump := dumpTrie(ltrie)
if dump != ldump {
t.Errorf("Insert() - different tries\norigin:\n%s\nother:\n%s\n", dump, ldump)
}
}
// error check
if trie.Insert([]byte("a"), nil) {
t.Error("Insert() - check exists")
}
if !trie.Insert([]byte("c"), nil) {
t.Error("Insert() - check not exists")
}
}
func TestSet(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
trie.Set([]byte("a"), 100)
v, _ := trie.Get([]byte("a"))
if n, ok := v.(int); !ok || n != 100 {
t.Errorf("Set() - failed replace - %v", v)
}
}
func TestContains(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
for _, key := range keys {
if !trie.Contains([]byte(key)) {
t.Error("Contains() - not found - %s", key)
}
}
if trie.Contains([]byte("aaa")) {
t.Error("Contains() - phantom found")
}
}
func TestGet(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
for _, key := range keys {
if value, ok := trie.Get([]byte(key)); value != key || !ok {
t.Error("Get() - not found - %s", key)
}
}
if value, ok := trie.Get([]byte("aaa")); value != nil || ok {
t.Error("Get() - phantom found")
}
}
func TestDelete(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
for i, key := range keys {
if !trie.Contains([]byte(key)) {
t.Error("Delete() - not exists - %s", key)
}
if v, ok := trie.Delete([]byte(key)); !ok || v != key {
t.Error("Delete() - failed - %s", key)
}
if trie.Contains([]byte(key)) {
t.Error("Delete() - exists - %s", key)
}
if i != len(keys) {
for _, key2 := range keys[i+1:] {
if !trie.Contains([]byte(key2)) {
t.Errorf("Delete() - other not exists - %s", key2)
}
}
}
}
}
func TestSize(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
klen := len(keys)
if s := trie.Size(); s != klen {
t.Errorf("Size() - expected [%s], actual [%s]", klen, s)
}
for i, key := range keys {
trie.Delete([]byte(key))
if s := trie.Size(); s != klen-(i+1) {
t.Errorf("Size() - expected [%s], actual [%s]", klen, s)
}
}
}
func TestAllprefixed(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
elems := make([]string, 0, len(keys))
handle := func(key []byte, value interface{}) bool {
if k := string(key); k == value {
elems = append(elems, k)
}
return true
}
if !trie.Allprefixed([]byte{}, handle) {
t.Error("Allprefixed() - invalid result")
}
if len(elems) != 9 {
t.Errorf("Allprefixed() - invalid elems length [%v]", elems)
}
for i, key := range []string{"", "a", "aa", "ab", "aba", "b", "ba", "bab", "bb"} {
if key != elems[i] {
t.Errorf("Allprefixed() - not found [%s]", key)
}
}
elems = make([]string, 0, len(keys))
if !trie.Allprefixed([]byte("a"), handle) {
t.Error("Allprefixed() - invalid result")
}
if len(elems) != 4 {
t.Errorf("Allprefixed() - invalid elems length [%v]", elems)
}
for i, key := range []string{"a", "aa", "ab", "aba"} {
if key != elems[i] {
t.Errorf("Allprefixed() - not found [%s]", key)
}
}
elems = make([]string, 0, len(keys))
handle = func(key []byte, value interface{}) bool {
if k := string(key); k == value {
elems = append(elems, k)
}
if string(key) == "aa" {
return false
}
return true
}
if trie.Allprefixed([]byte("a"), handle) {
t.Error("Allprefixed() - invalid result")
}
if len(elems) != 2 {
t.Errorf("Allprefixed() - invalid elems length [%v]", elems)
}
for i, key := range []string{"a", "aa"} {
if key != elems[i] {
t.Errorf("Allprefixed() - not found [%s]", key)
}
}
}
func TestLongestPrefix(t *testing.T) {
keys := []string{"a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
expects := map[string]string{
"a": "a",
"a^": "a",
"aaa": "aa",
"abc": "ab",
"bac": "ba",
"bbb": "bb",
"bc": "b",
}
for g, k := range expects {
if key, value, ok := trie.LongestPrefix([]byte(g)); !ok || string(key) != k || value != k {
t.Errorf("LongestPrefix() - invalid result - %s not %s", key, g)
}
}
if _, _, ok := trie.LongestPrefix([]byte{}); ok {
t.Error("LongestPrefix() - invalid result - not empty")
}
if _, _, ok := trie.LongestPrefix([]byte("^")); ok {
t.Error("LongestPrefix() - invalid result - not empty")
}
if _, _, ok := trie.LongestPrefix([]byte("c")); ok {
t.Error("LongestPrefix() - invalid result - not empty")
}
}
func TestWalk(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
trie := buildTrie(t, keys)
elems := make([]string, 0, len(keys))
handle := func(key []byte, value interface{}) bool {
if k := string(key); k == value {
elems = append(elems, k)
}
return true
}
if !trie.Walk([]byte{}, handle) {
t.Error("Walk() - invalid result")
}
if len(elems) != 9 {
t.Errorf("Walk() - invalid elems length [%v]", elems)
}
for i, key := range []string{"", "a", "aa", "ab", "aba", "b", "ba", "bab", "bb"} {
if key != elems[i] {
t.Errorf("Walk() - not found [%s]", key)
}
}
elems = make([]string, 0, len(keys))
if !trie.Walk([]byte("ab"), handle) {
t.Error("Walk() - invalid result")
}
if len(elems) != 6 {
t.Errorf("Walk() - invalid elems length [%v]", elems)
}
for i, key := range []string{"ab", "aba", "b", "ba", "bab", "bb"} {
if key != elems[i] {
t.Errorf("Walk() - not found [%s]", key)
}
}
elems = make([]string, 0, len(keys))
if !trie.Walk(nil, handle) {
t.Error("Walk() - invalid result")
}
if len(elems) != 9 {
t.Errorf("Walk() - invalid elems length [%v]", elems)
}
for i, key := range []string{"", "a", "aa", "ab", "aba", "b", "ba", "bab", "bb"} {
if key != elems[i] {
t.Errorf("Walk() - not found [%s]", key)
}
}
elems = make([]string, 0, len(keys))
handle = func(key []byte, value interface{}) bool {
if k := string(key); k == value {
elems = append(elems, k)
}
if string(key) == "aa" {
return false
}
return true
}
if trie.Walk([]byte("a"), handle) {
t.Error("Walk() - invalid result")
}
if len(elems) != 2 {
t.Errorf("Walk() - invalid elems length [%v]", elems)
}
for i, key := range []string{"a", "aa"} {
if key != elems[i] {
t.Errorf("Walk() - not found [%s]", key)
}
}
if trie.Walk([]byte("^"), handle) {
t.Error("Walk() - invalid result")
}
if trie.Walk([]byte("aaa"), handle) {
t.Error("Walk() - invalid result")
}
if trie.Walk([]byte("c"), handle) {
t.Error("Walk() - invalid result")
}
}
func TestKeyContainsZeroValue(t *testing.T) {
trie := critbitgo.NewTrie()
trie.Insert([]byte{1, 0, 1}, nil)
trie.Insert([]byte{1}, nil)
trie.Insert([]byte{0, 1, 1}, nil)
trie.Insert([]byte{}, nil)
trie.Insert([]byte{0, 0, 1}, nil)
trie.Insert([]byte{1, 1}, nil)
trie.Insert([]byte{1, 1, 1}, nil)
trie.Insert([]byte{0, 1}, nil)
trie.Insert([]byte{0, 1, 0}, nil)
trie.Insert([]byte{0, 0}, nil)
trie.Insert([]byte{0, 0, 0}, nil)
trie.Insert([]byte{0}, nil)
var index int
exp := [][]byte{
[]byte{},
[]byte{0},
[]byte{0, 0},
[]byte{0, 0, 0},
[]byte{0, 0, 1},
[]byte{0, 1},
[]byte{0, 1, 0},
[]byte{0, 1, 1},
[]byte{1},
[]byte{1, 0, 1},
[]byte{1, 1},
[]byte{1, 1, 1},
}
handle := func(key []byte, _ interface{}) bool {
if !bytes.Equal(exp[index], key) {
t.Errorf("Key Order - index=%d, expected [%x], actula [%x]", index, exp[index], key)
}
index += 1
return true
}
trie.Allprefixed([]byte(""), handle)
}

57
vendor/github.com/k-sone/critbitgo/map.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
package critbitgo
import (
"unsafe"
)
// The map is sorted according to the natural ordering of its keys
type SortedMap struct {
trie *Trie
}
func (m *SortedMap) Contains(key string) bool {
return m.trie.Contains(*(*[]byte)(unsafe.Pointer(&key)))
}
func (m *SortedMap) Get(key string) (value interface{}, ok bool) {
return m.trie.Get(*(*[]byte)(unsafe.Pointer(&key)))
}
func (m *SortedMap) Set(key string, value interface{}) {
m.trie.Set([]byte(key), value)
}
func (m *SortedMap) Delete(key string) (value interface{}, ok bool) {
return m.trie.Delete(*(*[]byte)(unsafe.Pointer(&key)))
}
func (m *SortedMap) Clear() {
m.trie.Clear()
}
func (m *SortedMap) Size() int {
return m.trie.Size()
}
// Returns a slice of sorted keys
func (m *SortedMap) Keys() []string {
keys := make([]string, 0, m.Size())
m.trie.Allprefixed([]byte{}, func(k []byte, v interface{}) bool {
keys = append(keys, string(k))
return true
})
return keys
}
// Executes a provided function for each element that has a given prefix.
// if handle returns `false`, the iteration is aborted.
func (m *SortedMap) Each(prefix string, handle func(key string, value interface{}) bool) bool {
return m.trie.Allprefixed([]byte(prefix), func(k []byte, v interface{}) bool {
return handle(string(k), v)
})
}
// Create a SortedMap
func NewSortedMap() *SortedMap {
return &SortedMap{NewTrie()}
}

119
vendor/github.com/k-sone/critbitgo/map_bench_test.go generated vendored Normal file
View File

@ -0,0 +1,119 @@
package critbitgo_test
import (
"bytes"
"math/rand"
"sort"
"testing"
)
var keyCount int = 10000
var keyLen int = 128
var keys []string
var alphabet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var alphalen int = len(alphabet)
func init() {
keys = make([]string, keyCount)
random := rand.New(rand.NewSource(0))
for i := 0; i < len(keys); i++ {
keys[i] = genRandomKey(random)
}
}
func genRandomKey(rand *rand.Rand) string {
buf := bytes.NewBufferString("")
for i := 0; i < keyLen; i++ {
buf.WriteByte(alphabet[rand.Intn(alphalen)])
}
return buf.String()
}
func buildMap(keys []string) map[string]string {
m := make(map[string]string)
for _, key := range keys {
m[key] = key
}
return m
}
func BenchmarkMapBuild(b *testing.B) {
for i := 0; i < b.N; i++ {
buildMap(keys)
}
}
func BenchmarkSortedMapBuild(b *testing.B) {
for i := 0; i < b.N; i++ {
buildSortedMap(keys)
}
}
func BenchmarkMapGet(b *testing.B) {
m := buildMap(keys)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := keys[random.Intn(keyCount)]
_ = m[k]
}
}
func BenchmarkSortedMapGet(b *testing.B) {
m := buildSortedMap(keys)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := keys[random.Intn(keyCount)]
_, _ = m.Get(k)
}
}
func BenchmarkMapDelete(b *testing.B) {
m := buildMap(keys)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := keys[random.Intn(keyCount)]
if _, ok := m[k]; ok {
delete(m, k)
}
}
}
func BenchmarkSortedMapDelete(b *testing.B) {
m := buildSortedMap(keys)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := keys[random.Intn(keyCount)]
m.Delete(k)
}
}
func BenchmarkMapKeys(b *testing.B) {
m := buildMap(keys)
b.ResetTimer()
for i := 0; i < b.N; i++ {
list := make([]string, 0, len(m))
for _, k := range m {
list = append(list, k)
}
sort.Strings(list)
}
}
func BenchmarkSortedMapKeys(b *testing.B) {
m := buildSortedMap(keys)
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.Keys()
}
}

164
vendor/github.com/k-sone/critbitgo/map_test.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
package critbitgo_test
import (
"strings"
"testing"
"github.com/k-sone/critbitgo"
)
func buildSortedMap(keys []string) *critbitgo.SortedMap {
m := critbitgo.NewSortedMap()
for _, key := range keys {
m.Set(key, key)
}
return m
}
func TestSortedMapContains(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
for _, key := range keys {
if !m.Contains(key) {
t.Error("Contains() - not found - [%s]", key)
}
}
if m.Contains("aaa") {
t.Error("Contains() - phantom found")
}
}
func TestSortedMapGet(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
for _, key := range keys {
if value, ok := m.Get(key); !ok || value != key {
t.Error("Get() - not found - [%s]", key)
}
}
if value, ok := m.Get("aaa"); ok || value != nil {
t.Error("Get() - phantom found")
}
}
func TestSortedMapDelete(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
for i, key := range keys {
if !m.Contains(key) {
t.Error("Delete() - not exists - [%s]", key)
}
if value, ok := m.Delete(key); !ok || value != key {
t.Error("Delete() - failed - [%s]", key)
}
if m.Contains(key) {
t.Error("Delete() - exists - [%s]", key)
}
if value, ok := m.Delete(key); ok || value != nil {
t.Error("Delete() - phantom found - [%s]", key)
}
if i != len(keys) {
for _, key2 := range keys[i+1:] {
if !m.Contains(key2) {
t.Errorf("Delete() - other not exists - [%s](%s)", key2, key)
}
}
}
}
}
func TestSortedMapSize(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
klen := len(keys)
if s := m.Size(); s != klen {
t.Errorf("Size() - expected [%s], actual [%s]", klen, s)
}
for i, key := range keys {
m.Delete(key)
if s := m.Size(); s != klen-(i+1) {
t.Errorf("Size() - expected [%s], actual [%s]", klen, s)
}
}
}
func TestSortedMapKeys(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
skeys := m.Keys()
for _, key := range keys {
match := false
for _, skey := range skeys {
if key == skey {
match = true
break
}
}
if !match {
t.Errorf("Keys() - not found [%s]", key)
}
}
}
func TestSortedMapEach(t *testing.T) {
keys := []string{"", "a", "aa", "b", "bb", "ab", "ba", "aba", "bab"}
m := buildSortedMap(keys)
elems := make(map[string]interface{})
handle := func(key string, value interface{}) bool {
elems[key] = value
return true
}
if !m.Each("", handle) {
t.Error("Each() - invalid result")
}
for _, key := range keys {
if _, ok := elems[key]; !ok {
t.Errorf("Each() - not found [%s]", key)
} else if value, ok := elems[key].(string); !ok || value != key {
t.Errorf("Each() - invalid value [%s](%s)", value, key)
}
}
elems = make(map[string]interface{})
handle = func(key string, value interface{}) bool {
elems[key] = value
return true
}
if !m.Each("b", handle) {
t.Error("Each() - invalid result")
}
for _, key := range keys {
if strings.Index(key, "b") == 0 {
if _, ok := elems[key]; !ok {
t.Errorf("Each() - not found [%s]", key)
} else if value, ok := elems[key].(string); !ok || value != key {
t.Errorf("Each() - invalid value [%s](%s)", value, key)
}
} else {
if _, ok := elems[key]; ok {
t.Errorf("Each() - phantom found [%s]", key)
}
}
}
elems = make(map[string]interface{})
handle = func(key string, value interface{}) bool {
elems[key] = value
return true
}
if !m.Each("c", handle) {
t.Error("Each() - invalid result")
}
for _, key := range keys {
if _, ok := elems[key]; ok {
t.Errorf("Each() - phantom found [%s]", key)
}
}
}

228
vendor/github.com/k-sone/critbitgo/net.go generated vendored Normal file
View File

@ -0,0 +1,228 @@
package critbitgo
import (
"net"
)
var (
mask32 = net.IPMask{0xff, 0xff, 0xff, 0xff}
mask128 = net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)
// IP routing table.
type Net struct {
trie *Trie
}
// Add a route.
// If `r` is not IPv4/IPv6 network, returns an error.
func (n *Net) Add(r *net.IPNet, value interface{}) (err error) {
var ip net.IP
if ip, _, err = netValidateIPNet(r); err == nil {
n.trie.Set(netIPNetToKey(ip, r.Mask), value)
}
return
}
// Add a route.
// If `s` is not CIDR notation, returns an error.
func (n *Net) AddCIDR(s string, value interface{}) (err error) {
var r *net.IPNet
if _, r, err = net.ParseCIDR(s); err == nil {
n.Add(r, value)
}
return
}
// Delete a specific route.
// If `r` is not IP4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Delete(r *net.IPNet) (value interface{}, ok bool, err error) {
var ip net.IP
if ip, _, err = netValidateIPNet(r); err == nil {
value, ok = n.trie.Delete(netIPNetToKey(ip, r.Mask))
}
return
}
// Delete a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) DeleteCIDR(s string) (value interface{}, ok bool, err error) {
var r *net.IPNet
if _, r, err = net.ParseCIDR(s); err == nil {
value, ok, err = n.Delete(r)
}
return
}
// Get a specific route.
// If `r` is not IPv4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Get(r *net.IPNet) (value interface{}, ok bool, err error) {
var ip net.IP
if ip, _, err = netValidateIPNet(r); err == nil {
value, ok = n.trie.Get(netIPNetToKey(ip, r.Mask))
}
return
}
// Get a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) GetCIDR(s string) (value interface{}, ok bool, err error) {
var r *net.IPNet
if _, r, err = net.ParseCIDR(s); err == nil {
value, ok, err = n.Get(r)
}
return
}
// Return a specific route by using the longest prefix matching.
// If `r` is not IPv4/IPv6 network or a route is not found, `route` is nil.
func (n *Net) Match(r *net.IPNet) (route *net.IPNet, value interface{}, err error) {
var ip net.IP
if ip, _, err = netValidateIP(r.IP); err == nil {
if k, v := n.match(netIPNetToKey(ip, r.Mask)); k != nil {
route = netKeyToIPNet(k)
value = v
}
}
return
}
// Return a specific route by using the longest prefix matching.
// If `s` is not CIDR notation, or a route is not found, `route` is nil.
func (n *Net) MatchCIDR(s string) (route *net.IPNet, value interface{}, err error) {
var r *net.IPNet
if _, r, err = net.ParseCIDR(s); err == nil {
route, value, err = n.Match(r)
}
return
}
// Return a specific route by using the longest prefix matching.
// If `ip` is invalid IP, or a route is not found, `route` is nil.
func (n *Net) MatchIP(ip net.IP) (route *net.IPNet, value interface{}, err error) {
var isV4 bool
ip, isV4, err = netValidateIP(ip)
if err != nil {
return
}
var mask net.IPMask
if isV4 {
mask = mask32
} else {
mask = mask128
}
if k, v := n.match(netIPNetToKey(ip, mask)); k != nil {
route = netKeyToIPNet(k)
value = v
}
return
}
func (n *Net) match(key []byte) ([]byte, interface{}) {
if n.trie.size > 0 {
if node := lookup(&n.trie.root, key, false); node != nil {
return node.external.key, node.external.value
}
}
return nil, nil
}
func lookup(p *node, key []byte, backtracking bool) *node {
if p.internal != nil {
var direction int
if p.internal.offset == len(key)-1 {
// selecting the larger side when comparing the mask
direction = 1
} else if backtracking {
direction = 0
} else {
direction = p.internal.direction(key)
}
if c := lookup(&p.internal.child[direction], key, backtracking); c != nil {
return c
}
if direction == 1 {
// search other node
return lookup(&p.internal.child[0], key, true)
}
return nil
} else {
nlen := len(p.external.key)
if nlen != len(key) {
return nil
}
// check mask
mask := p.external.key[nlen-1]
if mask > key[nlen-1] {
return nil
}
// compare both keys with mask
div := int(mask >> 3)
for i := 0; i < div; i++ {
if p.external.key[i] != key[i] {
return nil
}
}
if mod := uint(mask & 0x07); mod > 0 {
bit := 8 - mod
if p.external.key[div] != key[div]&(0xff>>bit<<bit) {
return nil
}
}
return p
}
}
// Deletes all routes.
func (n *Net) Clear() {
n.trie.Clear()
}
// Returns number of routes.
func (n *Net) Size() int {
return n.trie.Size()
}
// Create IP routing table
func NewNet() *Net {
return &Net{NewTrie()}
}
func netValidateIP(ip net.IP) (nIP net.IP, isV4 bool, err error) {
if v4 := ip.To4(); v4 != nil {
nIP = v4
isV4 = true
} else if ip.To16() != nil {
nIP = ip
} else {
err = &net.AddrError{Err: "Invalid IP address", Addr: ip.String()}
}
return
}
func netValidateIPNet(r *net.IPNet) (nIP net.IP, isV4 bool, err error) {
if r == nil {
err = &net.AddrError{Err: "IP network is nil"}
return
}
return netValidateIP(r.IP)
}
func netIPNetToKey(ip net.IP, mask net.IPMask) []byte {
// +--------------+------+
// | ip address.. | mask |
// +--------------+------+
ones, _ := mask.Size()
return append(ip, byte(ones))
}
func netKeyToIPNet(k []byte) *net.IPNet {
iplen := len(k) - 1
return &net.IPNet{
IP: net.IP(k[:iplen]),
Mask: net.CIDRMask(int(k[iplen]), iplen*8),
}
}

78
vendor/github.com/k-sone/critbitgo/net_bench_test.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
package critbitgo_test
import (
"math/rand"
"net"
"testing"
"github.com/k-sone/critbitgo"
)
var routeCount int = 10000
var routes []string
func init() {
routes = make([]string, routeCount)
random := rand.New(rand.NewSource(0))
for i := 0; i < len(routes); i++ {
routes[i] = genRoute(random)
}
}
func genRoute(rand *rand.Rand) string {
ip := rand.Int31()
mask := rand.Intn(33)
ipnet := &net.IPNet{
IP: net.IP{byte(ip >> 24), byte(ip >> 16), byte(ip >> 8), byte(ip)},
Mask: net.CIDRMask(mask, 32),
}
return ipnet.String()
}
func buildNet(keys []string) *critbitgo.Net {
tree := critbitgo.NewNet()
for i := 0; i < len(keys); i++ {
tree.AddCIDR(keys[i], nil)
}
tree.AddCIDR("0.0.0.0/5", nil)
return tree
}
func BenchmarkNetBuild(b *testing.B) {
for i := 0; i < b.N; i++ {
buildNet(routes)
}
}
func BenchmarkNetGet(b *testing.B) {
n := buildNet(routes)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := routes[random.Intn(routeCount)]
n.GetCIDR(k)
}
}
func BenchmarkNetDelete(b *testing.B) {
n := buildNet(routes)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
k := routes[random.Intn(keyCount)]
n.DeleteCIDR(k)
}
}
func BenchmarkNetMatch(b *testing.B) {
n := buildNet(routes)
random := rand.New(rand.NewSource(0))
b.ResetTimer()
for i := 0; i < b.N; i++ {
s := genRoute(random)
n.MatchCIDR(s)
}
}

110
vendor/github.com/k-sone/critbitgo/net_test.go generated vendored Normal file
View File

@ -0,0 +1,110 @@
package critbitgo_test
import (
"net"
"testing"
"github.com/k-sone/critbitgo"
)
func TestNet(t *testing.T) {
trie := critbitgo.NewNet()
cidr := "192.168.1.0/24"
host := "192.168.1.1/32"
hostIP := net.IPv4(192, 168, 1, 1)
if _, _, err := trie.GetCIDR(""); err == nil {
t.Error("GetCIDR() - not error")
}
if v, ok, err := trie.GetCIDR(cidr); v != nil || ok || err != nil {
t.Errorf("GetCIDR() - phantom: %v, %v, %v", v, ok, err)
}
if _, _, err := trie.MatchCIDR(""); err == nil {
t.Error("MatchCIDR() - not error")
}
if r, v, err := trie.MatchCIDR(host); r != nil || v != nil || err != nil {
t.Errorf("MatchCIDR() - phantom: %v, %v, %v", r, v, err)
}
if _, _, err := trie.MatchIP(net.IP([]byte{})); err == nil {
t.Error("MatchIP() - not error")
}
if r, v, err := trie.MatchIP(hostIP); r != nil || v != nil || err != nil {
t.Errorf("MatchIP() - phantom: %v, %v, %v", r, v, err)
}
if _, _, err := trie.DeleteCIDR(""); err == nil {
t.Error("DeleteCIDR() - not error")
}
if v, ok, err := trie.DeleteCIDR(cidr); v != nil || ok || err != nil {
t.Errorf("DeleteCIDR() - phantom: %v, %v, %v", v, ok, err)
}
if err := trie.AddCIDR(cidr, &cidr); err != nil {
t.Errorf("AddCIDR() - %s: error occurred %s", cidr, err)
}
if v, ok, err := trie.GetCIDR(cidr); v != &cidr || !ok || err != nil {
t.Errorf("GetCIDR() - failed: %v, %v, %v", v, ok, err)
}
if r, v, err := trie.MatchCIDR(host); r == nil || r.String() != cidr || v != &cidr || err != nil {
t.Errorf("MatchCIDR() - failed: %v, %v, %v", r, v, err)
}
if r, v, err := trie.MatchIP(hostIP); r == nil || r.String() != cidr || v != &cidr || err != nil {
t.Errorf("MatchIP() - failed: %v, %v, %v", r, v, err)
}
if v, ok, err := trie.DeleteCIDR(cidr); v != &cidr || !ok || err != nil {
t.Errorf("DeleteCIDR() - failed: %v, %v, %v", v, ok, err)
}
}
func checkMatch(t *testing.T, trie *critbitgo.Net, request, expect string) {
route, value, err := trie.MatchCIDR(request)
if err != nil {
t.Errorf("MatchCIDR() - %s: error occurred %s", request, err)
}
if cidr := route.String(); expect != cidr {
t.Errorf("MatchCIDR() - %s: expected [%s], actual [%s]", request, expect, cidr)
}
if value == nil {
t.Errorf("MatchCIDR() - %s: no value", request)
}
}
func TestNetMatch(t *testing.T) {
trie := critbitgo.NewNet()
cidrs := []string{
"0.0.0.0/4",
"192.168.0.0/16",
"192.168.1.0/24",
"192.168.1.0/28",
"192.168.1.0/32",
"192.168.1.1/32",
"192.168.1.2/32",
"192.168.1.32/27",
"192.168.1.32/30",
"192.168.2.1/32",
"192.168.2.2/32",
}
for _, cidr := range cidrs {
if err := trie.AddCIDR(cidr, &cidr); err != nil {
t.Errorf("AddCIDR() - %s: error occurred %s", cidr, err)
}
}
checkMatch(t, trie, "10.0.0.0/8", "0.0.0.0/4")
checkMatch(t, trie, "192.168.1.0/24", "192.168.1.0/24")
checkMatch(t, trie, "192.168.1.0/30", "192.168.1.0/28")
checkMatch(t, trie, "192.168.1.0/32", "192.168.1.0/32")
checkMatch(t, trie, "192.168.1.128/26", "192.168.1.0/24")
checkMatch(t, trie, "192.168.2.128/26", "192.168.0.0/16")
checkMatch(t, trie, "192.168.1.1/32", "192.168.1.1/32")
checkMatch(t, trie, "192.168.1.2/32", "192.168.1.2/32")
checkMatch(t, trie, "192.168.1.3/32", "192.168.1.0/28")
checkMatch(t, trie, "192.168.1.32/32", "192.168.1.32/30")
checkMatch(t, trie, "192.168.1.35/32", "192.168.1.32/30")
checkMatch(t, trie, "192.168.1.36/32", "192.168.1.32/27")
checkMatch(t, trie, "192.168.1.63/32", "192.168.1.32/27")
checkMatch(t, trie, "192.168.1.64/32", "192.168.1.0/24")
checkMatch(t, trie, "192.168.2.2/32", "192.168.2.2/32")
checkMatch(t, trie, "192.168.2.3/32", "192.168.0.0/16")
}